Repository: HQSquantumsimulations/qoqo (language: python)

Issue:
Remove Python::acquire_gil() from unittests
Following https://github.com/PyO3/pyo3/issues/1683 Python::acquire_gil() should be deprecated in favour of Python::with_gil().

Python::acquire_gil() will be removed from the main library in #40 but is still used in unittests


Discussion / hints:

Fix patch:
diff --git a/qoqo-macros/src/lib.rs b/qoqo-macros/src/lib.rs
index 230869bf..6a898b68 100644
--- a/qoqo-macros/src/lib.rs
+++ b/qoqo-macros/src/lib.rs
@@ -121,9 +121,9 @@ pub fn wrap(
             /// Returns:
             ///     np.ndarray
             pub fn superoperator(&self) -> PyResult<Py<PyArray2<f64>>>{
-                let gil = Python::acquire_gil();
-                let py = gil.python();
-                Ok(self.internal.superoperator().unwrap().to_pyarray(py).to_owned())
+                Python::with_gil(|py| -> PyResult<Py<PyArray2<f64>>> {
+                    Ok(self.internal.superoperator().unwrap().to_pyarray(py).to_owned())
+                })
             }
             /// Return the power of the noise gate
             ///
@@ -281,9 +281,9 @@ pub fn wrap(
             /// Raises:
             ///     ValueError: Error symbolic operation cannot return float unitary matrix
             pub fn unitary_matrix(&self) -> PyResult<Py<PyArray2<Complex64>>>{
-                let gil = Python::acquire_gil();
-                let py = gil.python();
-                Ok(self.internal.unitary_matrix().map_err(|x| PyValueError::new_err(format!("Error symbolic operation cannot return float unitary matrix {:?}",x)))?.to_pyarray(py).to_owned())
+                Python::with_gil(|py| -> PyResult<Py<PyArray2<Complex64>>> {
+                    Ok(self.internal.unitary_matrix().map_err(|x| PyValueError::new_err(format!("Error symbolic operation cannot return float unitary matrix {:?}",x)))?.to_pyarray(py).to_owned())
+                })
             }
         }
     } else {
@@ -380,34 +380,34 @@ pub fn wrap(
 
 
 
-        /// Returns the __richcmp__ magic method to perform rich comparison
-        /// operations on Operation.
-        ///
-        /// # Arguments
-        ///
-        /// * `&self` - the OperationWrapper object
-        /// * `other` - the object to compare self to
-        /// * `op` - equal or not equal
-        ///
-        /// # Returns
-        ///
-        /// `PyResult<bool>` - whether the two operations compared evaluated to True or False
-        ///
-        fn __richcmp__(&self, other: Py<PyAny>, op: pyo3::class::basic::CompareOp) -> PyResult<bool> {
-            let gil = pyo3::Python::acquire_gil();
-            let py = gil.python();
-            let other_ref = other.as_ref(py);
-            let other: Operation = crate::operations::convert_pyany_to_operation(other_ref).map_err(|x| {
-                pyo3::exceptions::PyTypeError::new_err(format!("Right hand side cannot be converted to Operation {:?}",x))
-            })?;
-            match op {
-                pyo3::class::basic::CompareOp::Eq => Ok(Operation::from(self.internal.clone()) == other),
-                pyo3::class::basic::CompareOp::Ne => Ok(Operation::from(self.internal.clone()) != other),
-                _ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
-                    "Other comparison not implemented.",
-                )),
+            /// Returns the __richcmp__ magic method to perform rich comparison
+            /// operations on Operation.
+            ///
+            /// # Arguments
+            ///
+            /// * `&self` - the OperationWrapper object
+            /// * `other` - the object to compare self to
+            /// * `op` - equal or not equal
+            ///
+            /// # Returns
+            ///
+            /// `PyResult<bool>` - whether the two operations compared evaluated to True or False
+            ///
+            fn __richcmp__(&self, other: Py<PyAny>, op: pyo3::class::basic::CompareOp) -> PyResult<bool> {
+                Python::with_gil(|py| -> PyResult<bool> {
+                    let other_ref = other.as_ref(py);
+                    let other: Operation = crate::operations::convert_pyany_to_operation(other_ref).map_err(|x| {
+                        pyo3::exceptions::PyTypeError::new_err(format!("Right hand side cannot be converted to Operation {:?}",x))
+                    })?;
+                    match op {
+                        pyo3::class::basic::CompareOp::Eq => Ok(Operation::from(self.internal.clone()) == other),
+                        pyo3::class::basic::CompareOp::Ne => Ok(Operation::from(self.internal.clone()) != other),
+                        _ => Err(pyo3::exceptions::PyNotImplementedError::new_err(
+                            "Other comparison not implemented.",
+                        )),
+                    }
+                })
             }
-        }
 
         }
     };
diff --git a/qoqo-macros/src/operate.rs b/qoqo-macros/src/operate.rs
index 20769b55..892c3050 100644
--- a/qoqo-macros/src/operate.rs
+++ b/qoqo-macros/src/operate.rs
@@ -244,31 +244,30 @@ fn operate_struct(ds: DataStruct, ident: Ident) -> TokenStream {
         /// Returns:
         ///     Union[set[int], str]: The involved qubits as a set or 'ALL' if all qubits are involved
         fn involved_qubits(&self) -> PyObject {
-            let gil = Python::acquire_gil();
-            let py = gil.python();
-
-            let involved = self.internal.involved_qubits();
-            match involved {
-                InvolvedQubits::All => {
-                    let pyref: &PySet = PySet::new(py, &["All"]).unwrap();
-                    let pyobject: PyObject = pyref.to_object(py);
-                    pyobject
-                },
-                InvolvedQubits::None => {
-                    let pyref: &PySet = PySet::empty(py).unwrap();
-                    let pyobject: PyObject = pyref.to_object(py);
-                    pyobject
-                },
-                InvolvedQubits::Set(x) => {
-                    let mut vector: Vec<usize> = Vec::new();
-                    for qubit in x {
-                        vector.push(qubit)
-                    }
-                    let pyref: &PySet = PySet::new(py, &vector[..]).unwrap();
-                    let pyobject: PyObject = pyref.to_object(py);
-                    pyobject
-                },
-            }
+            Python::with_gil(|py| -> PyObject {
+                let involved = self.internal.involved_qubits();
+                match involved {
+                    InvolvedQubits::All => {
+                        let pyref: &PySet = PySet::new(py, &["All"]).unwrap();
+                        let pyobject: PyObject = pyref.to_object(py);
+                        pyobject
+                    },
+                    InvolvedQubits::None => {
+                        let pyref: &PySet = PySet::empty(py).unwrap();
+                        let pyobject: PyObject = pyref.to_object(py);
+                        pyobject
+                    },
+                    InvolvedQubits::Set(x) => {
+                        let mut vector: Vec<usize> = Vec::new();
+                        for qubit in x {
+                            vector.push(qubit)
+                        }
+                        let pyref: &PySet = PySet::new(py, &vector[..]).unwrap();
+                        let pyobject: PyObject = pyref.to_object(py);
+                        pyobject
+                    },
+                }
+            })
         }
 
         /// Copies Operation
diff --git a/qoqo/src/operations/pragma_operations.rs b/qoqo/src/operations/pragma_operations.rs
index f845be62..476d46ba 100644
--- a/qoqo/src/operations/pragma_operations.rs
+++ b/qoqo/src/operations/pragma_operations.rs
@@ -868,9 +868,7 @@ fn pragma_general_noise(_py: Python, module: &PyModule) -> PyResult<()> {
 /// Args:
 ///     qubit (int): The qubit the PRAGMA operation is applied to.
 ///     gate_time (CalculatorFloat): The time (in seconds) the gate takes to be applied to the qubit on the (simulated) hardware
-///     rate (CalculatorFloat): The error rate of the noise (in 1/second).
-///     operators (CalculatorFloat): The operators representing the general noise.
-///                                  The array needs to be flattened before input, using np.flatten.
+///     Rates: The rates representing the general noise matrix M (a 3x3 matrix as 1d array).
 ///
 pub struct PragmaGeneralNoiseWrapper {
     /// PragmaGeneralNoise to be wrapped and converted to Python.
@@ -1426,16 +1424,16 @@ mod tests {
         let input_definition: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(input_definition).unwrap();
-        let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
-        let involved_op: HashSet<&str> = HashSet::extract(to_involved.as_ref(py)).unwrap();
-        let mut involved_param: HashSet<&str> = HashSet::new();
-        involved_param.insert("All");
-        assert_eq!(involved_op, involved_param);
-
-        assert!(PragmaChangeDeviceWrapper::new().is_err());
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(input_definition).unwrap();
+            let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
+            let involved_op: HashSet<&str> = HashSet::extract(to_involved.as_ref(py)).unwrap();
+            let mut involved_param: HashSet<&str> = HashSet::new();
+            involved_param.insert("All");
+            assert_eq!(involved_op, involved_param);
+
+            assert!(PragmaChangeDeviceWrapper::new().is_err());
+        })
     }
 
     #[test]
@@ -1445,15 +1443,15 @@ mod tests {
         let format_repr = format!("PragmaChangeDevice {{ wrapped_tags: {:?}, wrapped_hqslang: {:?}, wrapped_operation: {:?} }}", wrapped.tags(), wrapped.hqslang(), serialize(&wrapped).unwrap());
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-        let to_repr = operation.call_method0(py, "__repr__").unwrap();
-        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-        assert_eq!(format_op, format_repr);
-        assert_eq!(repr_op, format_repr);
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+            let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+            let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+            let to_repr = operation.call_method0(py, "__repr__").unwrap();
+            let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+            assert_eq!(format_op, format_repr);
+            assert_eq!(repr_op, format_repr);
+        })
     }
 
     #[test]
@@ -1462,29 +1460,29 @@ mod tests {
         let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-        let copy_op = operation.call_method0(py, "__copy__").unwrap();
-        let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
-        let copy_deepcopy_param = operation.clone();
-
-        let comparison_copy = bool::extract(
-            copy_op
-                .as_ref(py)
-                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-                .unwrap(),
-        )
-        .unwrap();
-        assert!(comparison_copy);
-        let comparison_deepcopy = bool::extract(
-            deepcopy_op
-                .as_ref(py)
-                .call_method1("__eq__", (copy_deepcopy_param,))
-                .unwrap(),
-        )
-        .unwrap();
-        assert!(comparison_deepcopy);
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+            let copy_op = operation.call_method0(py, "__copy__").unwrap();
+            let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
+            let copy_deepcopy_param = operation.clone();
+
+            let comparison_copy = bool::extract(
+                copy_op
+                    .as_ref(py)
+                    .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                    .unwrap(),
+            )
+            .unwrap();
+            assert!(comparison_copy);
+            let comparison_deepcopy = bool::extract(
+                deepcopy_op
+                    .as_ref(py)
+                    .call_method1("__eq__", (copy_deepcopy_param,))
+                    .unwrap(),
+            )
+            .unwrap();
+            assert!(comparison_deepcopy);
+        })
     }
 
     #[test]
@@ -1493,13 +1491,13 @@ mod tests {
         let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-        let to_tag = operation.call_method0(py, "tags").unwrap();
-        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-        let tags_param: &[&str] = &["Operation", "PragmaOperation", "PragmaChangeDevice"];
-        assert_eq!(tags_op, tags_param);
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+            let to_tag = operation.call_method0(py, "tags").unwrap();
+            let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+            let tags_param: &[&str] = &["Operation", "PragmaOperation", "PragmaChangeDevice"];
+            assert_eq!(tags_op, tags_param);
+        })
     }
 
     #[test]
@@ -1508,12 +1506,12 @@ mod tests {
         let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-        let hqslang_op: String =
-            String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
-        assert_eq!(hqslang_op, "PragmaChangeDevice".to_string());
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+            let hqslang_op: String =
+                String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
+            assert_eq!(hqslang_op, "PragmaChangeDevice".to_string());
+        })
     }
 
     #[test]
@@ -1522,16 +1520,16 @@ mod tests {
         let input_measurement: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-        assert!(!bool::extract(
-            operation
-                .call_method0(py, "is_parametrized")
-                .unwrap()
-                .as_ref(py)
-        )
-        .unwrap());
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+            assert!(!bool::extract(
+                operation
+                    .call_method0(py, "is_parametrized")
+                    .unwrap()
+                    .as_ref(py)
+            )
+            .unwrap());
+        })
     }
 
     #[test]
@@ -1541,24 +1539,24 @@ mod tests {
         let second_op: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(first_op).unwrap();
-        let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
-        substitution_dict.insert("test", 1.0);
-        let substitute_op = operation
-            .call_method1(py, "substitute_parameters", (substitution_dict,))
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(first_op).unwrap();
+            let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
+            substitution_dict.insert("test", 1.0);
+            let substitute_op = operation
+                .call_method1(py, "substitute_parameters", (substitution_dict,))
+                .unwrap();
+            let substitute_param = convert_operation_to_pyobject(second_op).unwrap();
+
+            let comparison = bool::extract(
+                substitute_op
+                    .as_ref(py)
+                    .call_method1("__eq__", (substitute_param.clone(),))
+                    .unwrap(),
+            )
             .unwrap();
-        let substitute_param = convert_operation_to_pyobject(second_op).unwrap();
-
-        let comparison = bool::extract(
-            substitute_op
-                .as_ref(py)
-                .call_method1("__eq__", (substitute_param.clone(),))
-                .unwrap(),
-        )
-        .unwrap();
-        assert!(comparison);
+            assert!(comparison);
+        })
     }
 
     #[test]
@@ -1568,25 +1566,25 @@ mod tests {
         let second_op: Operation = PragmaChangeDevice::new(&wrapped).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(first_op).unwrap();
-
-        let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
-        qubit_mapping.insert(0, 0);
-        let remapped_op = operation
-            .call_method1(py, "remap_qubits", (qubit_mapping,))
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(first_op).unwrap();
+
+            let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
+            qubit_mapping.insert(0, 0);
+            let remapped_op = operation
+                .call_method1(py, "remap_qubits", (qubit_mapping,))
+                .unwrap();
+            let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
+
+            let comparison = bool::extract(
+                remapped_op
+                    .call_method1(py, "__eq__", (comparison_op,))
+                    .unwrap()
+                    .as_ref(py),
+            )
             .unwrap();
-        let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
-
-        let comparison = bool::extract(
-            remapped_op
-                .call_method1(py, "__eq__", (comparison_op,))
-                .unwrap()
-                .as_ref(py),
-        )
-        .unwrap();
-        assert!(comparison);
+            assert!(comparison);
+        })
     }
 
     #[test]
@@ -1595,14 +1593,14 @@ mod tests {
         let first_op: Operation = PragmaChangeDevice::new(&wrapped.clone()).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation = convert_operation_to_pyobject(first_op).unwrap();
+        Python::with_gil(|py| -> () {
+            let operation = convert_operation_to_pyobject(first_op).unwrap();
 
-        let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
-        qubit_mapping.insert(0, 2);
-        let remapped_op = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
-        assert!(remapped_op.is_err());
+            let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
+            qubit_mapping.insert(0, 2);
+            let remapped_op = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
+            assert!(remapped_op.is_err());
+        })
     }
 
     #[test]
@@ -1613,33 +1611,33 @@ mod tests {
         let definition_2: Operation = PragmaChangeDevice::new(&wrapped_2).unwrap().into();
 
         pyo3::prepare_freethreaded_python();
-        let gil = pyo3::Python::acquire_gil();
-        let py = gil.python();
-        let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
-        let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
-
-        let comparison = bool::extract(
-            operation_one
-                .as_ref(py)
-                .call_method1("__eq__", (operation_two.clone(),))
-                .unwrap(),
-        )
-        .unwrap();
-        assert!(!comparison);
-
-        let comparison = bool::extract(
-            operation_one
-                .as_ref(py)
-                .call_method1("__ne__", (operation_two.clone(),))
-                .unwrap(),
-        )
-        .unwrap();
-        assert!(comparison);
-
-        let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
-        assert!(comparison.is_err());
-
-        let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
-        assert!(comparison.is_err());
+        Python::with_gil(|py| -> () {
+            let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
+            let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
+
+            let comparison = bool::extract(
+                operation_one
+                    .as_ref(py)
+                    .call_method1("__eq__", (operation_two.clone(),))
+                    .unwrap(),
+            )
+            .unwrap();
+            assert!(!comparison);
+
+            let comparison = bool::extract(
+                operation_one
+                    .as_ref(py)
+                    .call_method1("__ne__", (operation_two.clone(),))
+                    .unwrap(),
+            )
+            .unwrap();
+            assert!(comparison);
+
+            let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
+            assert!(comparison.is_err());
+
+            let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
+            assert!(comparison.is_err());
+        })
     }
 }
diff --git a/qoqo/src/operations/two_qubit_gate_operations.rs b/qoqo/src/operations/two_qubit_gate_operations.rs
index b2d33c1b..3c418ae4 100644
--- a/qoqo/src/operations/two_qubit_gate_operations.rs
+++ b/qoqo/src/operations/two_qubit_gate_operations.rs
@@ -496,7 +496,7 @@ pub struct ComplexPMInteraction {
 #[wrap(Operate, OperateTwoQubit, OperateGate, OperateTwoQubitGate)]
 /// The phased-shifted controlled-Z gate.
 ///
-/// Modified, i.e. phase-shifted ControlledPauliZ two-qubit gate (https://arxiv.org/pdf/1908.06101.pdf eq.(1)).
+/// Modified, i.e. phase-shifted ControlledPauliZ two-qubit gate (`<https://arxiv.org/pdf/1908.06101.pdf eq.(1)>`).
 ///
 /// The unitary matrix representation is:
 ///
diff --git a/roqoqo/src/operations/two_qubit_gate_operations.rs b/roqoqo/src/operations/two_qubit_gate_operations.rs
index 65e09673..ce4ba7c5 100644
--- a/roqoqo/src/operations/two_qubit_gate_operations.rs
+++ b/roqoqo/src/operations/two_qubit_gate_operations.rs
@@ -2154,7 +2154,7 @@ impl OperateTwoQubitGate for ComplexPMInteraction {
 
 /// Implements the phased-shifted controlled-Z gate.
 ///
-/// Modified, i.e. phase-shifted ControlledPauliZ two-qubit gate (https://arxiv.org/pdf/1908.06101.pdf eq.(1)).
+/// Modified, i.e. phase-shifted ControlledPauliZ two-qubit gate (`<https://arxiv.org/pdf/1908.06101.pdf eq.(1)>`).
 /// The unitary matrix representation is:
 ///
 /// $$


Test patch:
diff --git a/qoqo/tests/integration/circuit.rs b/qoqo/tests/integration/circuit.rs
index 0196f311..df701d26 100644
--- a/qoqo/tests/integration/circuit.rs
+++ b/qoqo/tests/integration/circuit.rs
@@ -53,6 +53,7 @@ fn populate_circuit_rotatex(
 #[test]
 fn test_default() {
     let operation = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
+    pyo3::prepare_freethreaded_python();
     Python::with_gil(|py| -> () {
         let circuit = new_circuit(py);
         circuit.call_method1("add", (operation.clone(),)).unwrap();
@@ -73,67 +74,68 @@ fn test_default() {
 /// Test substitute_parameters function of Circuit
 #[test]
 fn test_substitute_parameters() {
-    let added_operation = Operation::from(RotateX::new(0, CalculatorFloat::from("test")));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(added_operation).unwrap();
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation.clone(),)).unwrap();
-
-    let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
-    substitution_dict.insert("test", 1.0);
-    let substitute_circ = circuit
-        .call_method1("substitute_parameters", (substitution_dict,))
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let added_operation = Operation::from(RotateX::new(0, CalculatorFloat::from("test")));
 
-    let to_sub = Operation::from(RotateX::new(0, CalculatorFloat::from(1.0)));
-    let subbed_operation = convert_operation_to_pyobject(to_sub).unwrap();
+        let operation = convert_operation_to_pyobject(added_operation).unwrap();
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation.clone(),)).unwrap();
 
-    let comp_op = substitute_circ.call_method1("__getitem__", (0,)).unwrap();
-    let comparison =
-        bool::extract(comp_op.call_method1("__eq__", (subbed_operation,)).unwrap()).unwrap();
-    assert!(comparison);
+        let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
+        substitution_dict.insert("test", 1.0);
+        let substitute_circ = circuit
+            .call_method1("substitute_parameters", (substitution_dict,))
+            .unwrap();
+
+        let to_sub = Operation::from(RotateX::new(0, CalculatorFloat::from(1.0)));
+        let subbed_operation = convert_operation_to_pyobject(to_sub).unwrap();
 
-    let mut substitution_dict_error = HashMap::new();
-    substitution_dict_error.insert("fails", 0.0);
-    let comparison = circuit.call_method1("substitute_parameters", (substitution_dict_error,));
-    assert!(comparison.is_err());
+        let comp_op = substitute_circ.call_method1("__getitem__", (0,)).unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (subbed_operation,)).unwrap()).unwrap();
+        assert!(comparison);
+
+        let mut substitution_dict_error = HashMap::new();
+        substitution_dict_error.insert("fails", 0.0);
+        let comparison = circuit.call_method1("substitute_parameters", (substitution_dict_error,));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test remap_qubits function of Circuit
 #[test]
 fn test_remap_qubits() {
-    let added_operation = Operation::from(RotateX::new(0, CalculatorFloat::from(1.0)));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(added_operation).unwrap();
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation.clone(),)).unwrap();
-
-    let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    qubit_mapping.insert(0, 2);
-    let remap_circ = circuit
-        .call_method1("remap_qubits", (qubit_mapping,))
+    Python::with_gil(|py| -> () {
+        let added_operation = Operation::from(RotateX::new(0, CalculatorFloat::from(1.0)));
+        let operation = convert_operation_to_pyobject(added_operation).unwrap();
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation.clone(),)).unwrap();
+
+        let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        qubit_mapping.insert(0, 2);
+        let remap_circ = circuit
+            .call_method1("remap_qubits", (qubit_mapping,))
+            .unwrap();
+
+        let to_remap = Operation::from(RotateX::new(2, CalculatorFloat::from(1.0)));
+        let remapped_operation = convert_operation_to_pyobject(to_remap).unwrap();
+
+        let comp_op = remap_circ.call_method1("__getitem__", (0,)).unwrap();
+        let comparison = bool::extract(
+            comp_op
+                .call_method1("__eq__", (remapped_operation,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let to_remap = Operation::from(RotateX::new(2, CalculatorFloat::from(1.0)));
-    let remapped_operation = convert_operation_to_pyobject(to_remap).unwrap();
-
-    let comp_op = remap_circ.call_method1("__getitem__", (0,)).unwrap();
-    let comparison = bool::extract(
-        comp_op
-            .call_method1("__eq__", (remapped_operation,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let mut qubit_mapping_error = HashMap::new();
-    qubit_mapping_error.insert(5, 3);
-    let comparison = circuit.call_method1("remap_qubits", (qubit_mapping_error,));
-    assert!(comparison.is_err());
+        let mut qubit_mapping_error = HashMap::new();
+        qubit_mapping_error.insert(5, 3);
+        let comparison = circuit.call_method1("remap_qubits", (qubit_mapping_error,));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test count_occurences function of Circuit
@@ -142,52 +144,52 @@ fn test_count_occurences() {
     let added_op1 = Operation::from(DefinitionBit::new("ro".to_string(), 1, false));
     let added_op2 = Operation::from(RotateX::new(0, CalculatorFloat::from(1.0)));
     let added_op3 = Operation::from(PauliX::new(0));
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
     let operation1 = convert_operation_to_pyobject(added_op1).unwrap();
     let operation2 = convert_operation_to_pyobject(added_op2).unwrap();
     let operation3 = convert_operation_to_pyobject(added_op3).unwrap();
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation1.clone(),)).unwrap();
-    circuit.call_method1("add", (operation2.clone(),)).unwrap();
-    circuit.call_method1("add", (operation3.clone(),)).unwrap();
+    pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation1.clone(),)).unwrap();
+        circuit.call_method1("add", (operation2.clone(),)).unwrap();
+        circuit.call_method1("add", (operation3.clone(),)).unwrap();
 
-    let comp_op = usize::extract(
-        circuit
-            .call_method1("count_occurences", (vec!["Definition"],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(comp_op, 1_usize);
-    let comp_op = usize::extract(
-        circuit
-            .call_method1("count_occurences", (vec!["Operation"],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(comp_op, 3_usize);
-    let comp_op = usize::extract(
-        circuit
-            .call_method1("count_occurences", (vec!["RotateX"],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(comp_op, 1_usize);
-    let comp_op = usize::extract(
-        circuit
-            .call_method1("count_occurences", (vec!["SingleQubitGateOperation"],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(comp_op, 2_usize);
-    let comp_op = usize::extract(
-        circuit
-            .call_method1("count_occurences", (vec!["MadeUp"],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(comp_op, 0_usize);
+        let comp_op = usize::extract(
+            circuit
+                .call_method1("count_occurences", (vec!["Definition"],))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(comp_op, 1_usize);
+        let comp_op = usize::extract(
+            circuit
+                .call_method1("count_occurences", (vec!["Operation"],))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(comp_op, 3_usize);
+        let comp_op = usize::extract(
+            circuit
+                .call_method1("count_occurences", (vec!["RotateX"],))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(comp_op, 1_usize);
+        let comp_op = usize::extract(
+            circuit
+                .call_method1("count_occurences", (vec!["SingleQubitGateOperation"],))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(comp_op, 2_usize);
+        let comp_op = usize::extract(
+            circuit
+                .call_method1("count_occurences", (vec!["MadeUp"],))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(comp_op, 0_usize);
+    })
 }
 
 /// Test get_operation_types function of Circuit
@@ -196,287 +198,292 @@ fn test_get_operation_types() {
     let added_op1 = Operation::from(DefinitionBit::new("ro".to_string(), 1, false));
     let added_op2 = Operation::from(RotateX::new(0, CalculatorFloat::from(1.0)));
     let added_op3 = Operation::from(PauliX::new(0));
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
     let operation1 = convert_operation_to_pyobject(added_op1).unwrap();
     let operation2 = convert_operation_to_pyobject(added_op2).unwrap();
     let operation3 = convert_operation_to_pyobject(added_op3).unwrap();
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation1.clone(),)).unwrap();
-    circuit.call_method1("add", (operation2.clone(),)).unwrap();
-    circuit.call_method1("add", (operation3.clone(),)).unwrap();
-
-    let mut op_types: HashSet<&str> = HashSet::new();
-    op_types.insert("DefinitionBit");
-    op_types.insert("RotateX");
-    op_types.insert("PauliX");
-
-    let comp_op = HashSet::extract(circuit.call_method0("get_operation_types").unwrap()).unwrap();
-    assert_eq!(comp_op, op_types);
+    pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation1.clone(),)).unwrap();
+        circuit.call_method1("add", (operation2.clone(),)).unwrap();
+        circuit.call_method1("add", (operation3.clone(),)).unwrap();
+
+        let mut op_types: HashSet<&str> = HashSet::new();
+        op_types.insert("DefinitionBit");
+        op_types.insert("RotateX");
+        op_types.insert("PauliX");
+
+        let comp_op =
+            HashSet::extract(circuit.call_method0("get_operation_types").unwrap()).unwrap();
+        assert_eq!(comp_op, op_types);
+    })
 }
 
 /// Test copy and deepcopy functions of Circuit
 #[test]
 fn test_copy_deepcopy() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 3);
-
-    let copy_circ = circuit.call_method0("__copy__").unwrap();
-    let deepcopy_circ = circuit.call_method1("__deepcopy__", ("",)).unwrap();
-    let copy_deepcopy_param = circuit.clone();
-
-    let comparison_copy = bool::extract(
-        copy_circ
-            .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-    let comparison_deepcopy = bool::extract(
-        deepcopy_circ
-            .call_method1("__eq__", (copy_deepcopy_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 3);
+
+        let copy_circ = circuit.call_method0("__copy__").unwrap();
+        let deepcopy_circ = circuit.call_method1("__deepcopy__", ("",)).unwrap();
+        let copy_deepcopy_param = circuit.clone();
+
+        let comparison_copy = bool::extract(
+            copy_circ
+                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+        let comparison_deepcopy = bool::extract(
+            deepcopy_circ
+                .call_method1("__eq__", (copy_deepcopy_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 /// Test qoqo_versions function of Circuit
 #[test]
 fn test_qoqo_versions() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 3);
-    let mut rsplit = ROQOQO_VERSION.split('.').take(2);
-    let mut qsplit = QOQO_VERSION.split('.').take(2);
-    let rver = format!(
-        "{}.{}",
-        rsplit.next().expect("ROQOQO_VERSION badly formatted"),
-        rsplit.next().expect("ROQOQO_VERSION badly formatted")
-    );
-    let qver = format!(
-        "{}.{}",
-        qsplit.next().expect("QOQO_VERSION badly formatted"),
-        qsplit.next().expect("QOQO_VERSION badly formatted")
-    );
-
-    let comparison_copy: Vec<&str> =
-        Vec::extract(circuit.call_method0("_qoqo_versions").unwrap()).unwrap();
-    assert_eq!(comparison_copy, vec![rver.as_str(), qver.as_str()]);
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 3);
+        let mut rsplit = ROQOQO_VERSION.split('.').take(2);
+        let mut qsplit = QOQO_VERSION.split('.').take(2);
+        let rver = format!(
+            "{}.{}",
+            rsplit.next().expect("ROQOQO_VERSION badly formatted"),
+            rsplit.next().expect("ROQOQO_VERSION badly formatted")
+        );
+        let qver = format!(
+            "{}.{}",
+            qsplit.next().expect("QOQO_VERSION badly formatted"),
+            qsplit.next().expect("QOQO_VERSION badly formatted")
+        );
+
+        let comparison_copy: Vec<&str> =
+            Vec::extract(circuit.call_method0("_qoqo_versions").unwrap()).unwrap();
+        assert_eq!(comparison_copy, vec![rver.as_str(), qver.as_str()]);
+    })
 }
 
 /// Test to_ and from_bincode functions of Circuit
 #[test]
 fn test_to_from_bincode() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 3);
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 3);
 
-    let serialised = circuit.call_method0("to_bincode").unwrap();
-    let new = new_circuit(py);
-    let deserialised = new.call_method1("from_bincode", (serialised,)).unwrap();
+        let serialised = circuit.call_method0("to_bincode").unwrap();
+        let new = new_circuit(py);
+        let deserialised = new.call_method1("from_bincode", (serialised,)).unwrap();
 
-    let deserialised_error =
-        new.call_method1("from_bincode", (bincode::serialize("fails").unwrap(),));
-    assert!(deserialised_error.is_err());
+        let deserialised_error =
+            new.call_method1("from_bincode", (bincode::serialize("fails").unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let deserialised_error =
-        new.call_method1("from_bincode", (bincode::serialize(&vec![0]).unwrap(),));
-    assert!(deserialised_error.is_err());
+        let deserialised_error =
+            new.call_method1("from_bincode", (bincode::serialize(&vec![0]).unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let deserialised_error = deserialised.call_method0("from_bincode");
-    assert!(deserialised_error.is_err());
+        let deserialised_error = deserialised.call_method0("from_bincode");
+        assert!(deserialised_error.is_err());
 
-    let serialised_error = serialised.call_method0("to_bincode");
-    assert!(serialised_error.is_err());
+        let serialised_error = serialised.call_method0("to_bincode");
+        assert!(serialised_error.is_err());
 
-    let comparison =
-        bool::extract(deserialised.call_method1("__eq__", (circuit,)).unwrap()).unwrap();
-    assert!(comparison)
+        let comparison =
+            bool::extract(deserialised.call_method1("__eq__", (circuit,)).unwrap()).unwrap();
+        assert!(comparison)
+    })
 }
 
 #[test]
 fn test_value_error_bincode() {
     pyo3::prepare_freethreaded_python();
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<BasisRotationInputWrapper>();
-    let input = input_type
-        .call1((3, false))
-        .unwrap()
-        .cast_as::<PyCell<BasisRotationInputWrapper>>()
-        .unwrap();
-    let tmp_vec: Vec<usize> = Vec::new();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro", tmp_vec))
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<BasisRotationInputWrapper>();
+        let input = input_type
+            .call1((3, false))
+            .unwrap()
+            .cast_as::<PyCell<BasisRotationInputWrapper>>()
+            .unwrap();
+        let tmp_vec: Vec<usize> = Vec::new();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro", tmp_vec))
+            .unwrap();
 
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
 
-    let br_type = py.get_type::<BasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<BasisRotationWrapper>>()
-        .unwrap();
+        let br_type = py.get_type::<BasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<BasisRotationWrapper>>()
+            .unwrap();
 
-    let new_br = br.clone();
-    let serialised = br.call_method0("to_json").unwrap();
-    let deserialised = new_br
-        .call_method1("from_json", (serialised,))
-        .unwrap()
-        .cast_as::<PyCell<BasisRotationWrapper>>()
-        .unwrap();
+        let new_br = br.clone();
+        let serialised = br.call_method0("to_json").unwrap();
+        let deserialised = new_br
+            .call_method1("from_json", (serialised,))
+            .unwrap()
+            .cast_as::<PyCell<BasisRotationWrapper>>()
+            .unwrap();
 
-    let new = new_circuit(py);
-    let deserialised_error = new.call_method1("from_bincode", (deserialised,));
-    assert!(deserialised_error.is_err());
+        let new = new_circuit(py);
+        let deserialised_error = new.call_method1("from_bincode", (deserialised,));
+        assert!(deserialised_error.is_err());
+    })
 }
 
 /// Test to_ and from_json functions of Circuit
 #[test]
 fn test_to_from_json() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 3);
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 3);
 
-    let serialised = circuit.call_method0("to_json").unwrap();
-    let new = new_circuit(py);
-    let deserialised = new.call_method1("from_json", (serialised,)).unwrap();
+        let serialised = circuit.call_method0("to_json").unwrap();
+        let new = new_circuit(py);
+        let deserialised = new.call_method1("from_json", (serialised,)).unwrap();
 
-    let deserialised_error =
-        new.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
-    assert!(deserialised_error.is_err());
+        let deserialised_error =
+            new.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let deserialised_error =
-        new.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
-    assert!(deserialised_error.is_err());
+        let deserialised_error =
+            new.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let serialised_error = serialised.call_method0("to_json");
-    assert!(serialised_error.is_err());
+        let serialised_error = serialised.call_method0("to_json");
+        assert!(serialised_error.is_err());
 
-    let deserialised_error = deserialised.call_method0("from_json");
-    assert!(deserialised_error.is_err());
+        let deserialised_error = deserialised.call_method0("from_json");
+        assert!(deserialised_error.is_err());
 
-    let comparison =
-        bool::extract(deserialised.call_method1("__eq__", (circuit,)).unwrap()).unwrap();
-    assert!(comparison)
+        let comparison =
+            bool::extract(deserialised.call_method1("__eq__", (circuit,)).unwrap()).unwrap();
+        assert!(comparison)
+    })
 }
 
 ///  Test single index set and write access using "get" function
 #[test]
 fn test_single_index_access_get() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 3);
-
-    // test access at index 1
-    let comp_op = circuit.call_method1("get", (1,)).unwrap();
-    let operation =
-        convert_operation_to_pyobject(Operation::from(RotateX::new(1, CalculatorFloat::from(1))))
-            .unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation,)).unwrap()).unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 3);
+
+        // test access at index 1
+        let comp_op = circuit.call_method1("get", (1,)).unwrap();
+        let operation = convert_operation_to_pyobject(Operation::from(RotateX::new(
+            1,
+            CalculatorFloat::from(1),
+        )))
+        .unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation,)).unwrap()).unwrap();
+        assert!(comparison);
+
+        // test setting new operation at index 1
+        let operation2 = convert_operation_to_pyobject(Operation::from(RotateX::new(
+            1,
+            CalculatorFloat::from(10),
+        )))
+        .unwrap();
 
-    // test setting new operation at index 1
-    let operation2 =
-        convert_operation_to_pyobject(Operation::from(RotateX::new(1, CalculatorFloat::from(10))))
+        circuit
+            .call_method1("__setitem__", (1, operation2.clone()))
             .unwrap();
 
-    circuit
-        .call_method1("__setitem__", (1, operation2.clone()))
+        let comp_op = circuit.call_method1("get", (1,)).unwrap();
+        let comparison = bool::extract(
+            comp_op
+                .call_method1("__eq__", (operation2.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comp_op = circuit.call_method1("get", (1,)).unwrap();
-    let comparison = bool::extract(
-        comp_op
-            .call_method1("__eq__", (operation2.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let comparison = circuit.call_method1("get", (20,));
-    assert!(comparison.is_err());
+        let comparison = circuit.call_method1("get", (20,));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test get_slice property of Circuit
 #[test]
 fn test_get_slice() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 4);
-
-    let circuit2 = new_circuit(py);
-    populate_circuit_rotatex(py, circuit2, 1, 3);
-
-    let circuit3 = new_circuit(py);
-    populate_circuit_rotatex(py, circuit3, 0, 3);
-
-    let circuit4 = new_circuit(py);
-    populate_circuit_rotatex(py, circuit4, 2, 4);
-
-    let new_circuit_slice = circuit.call_method1("get_slice", (1, 2)).unwrap();
-    let comparison = bool::extract(
-        new_circuit_slice
-            .call_method1("__eq__", (circuit2,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let new_circuit_slice = circuit
-        .call_method1("get_slice", (Option::<usize>::None, 2))
-        .unwrap();
-    let comparison = bool::extract(
-        new_circuit_slice
-            .call_method1("__eq__", (circuit3,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let new_circuit_slice = circuit
-        .call_method1("get_slice", (2, Option::<usize>::None))
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 4);
+
+        let circuit2 = new_circuit(py);
+        populate_circuit_rotatex(py, circuit2, 1, 3);
+
+        let circuit3 = new_circuit(py);
+        populate_circuit_rotatex(py, circuit3, 0, 3);
+
+        let circuit4 = new_circuit(py);
+        populate_circuit_rotatex(py, circuit4, 2, 4);
+
+        let new_circuit_slice = circuit.call_method1("get_slice", (1, 2)).unwrap();
+        let comparison = bool::extract(
+            new_circuit_slice
+                .call_method1("__eq__", (circuit2,))
+                .unwrap(),
+        )
         .unwrap();
-    let comparison = bool::extract(
-        new_circuit_slice
-            .call_method1("__eq__", (circuit4,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    match circuit.call_method1("get_slice", (1, 20)) {
-        Err(x) => assert!(x.is_instance::<PyIndexError>(py)),
-        _ => panic!("Wrong error"),
-    }
+        assert!(comparison);
 
-    match circuit.call_method1("get_slice", (2, 1)) {
-        Err(x) => assert!(x.is_instance::<PyIndexError>(py)),
-        _ => panic!("Wrong error"),
-    }
+        let new_circuit_slice = circuit
+            .call_method1("get_slice", (Option::<usize>::None, 2))
+            .unwrap();
+        let comparison = bool::extract(
+            new_circuit_slice
+                .call_method1("__eq__", (circuit3,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
 
-    match circuit.call_method1("get_slice", (21, 22)) {
-        Err(x) => assert!(x.is_instance::<PyIndexError>(py)),
-        _ => panic!("Wrong error"),
-    }
+        let new_circuit_slice = circuit
+            .call_method1("get_slice", (2, Option::<usize>::None))
+            .unwrap();
+        let comparison = bool::extract(
+            new_circuit_slice
+                .call_method1("__eq__", (circuit4,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+
+        match circuit.call_method1("get_slice", (1, 20)) {
+            Err(x) => assert!(x.is_instance::<PyIndexError>(py)),
+            _ => panic!("Wrong error"),
+        }
+
+        match circuit.call_method1("get_slice", (2, 1)) {
+            Err(x) => assert!(x.is_instance::<PyIndexError>(py)),
+            _ => panic!("Wrong error"),
+        }
+
+        match circuit.call_method1("get_slice", (21, 22)) {
+            Err(x) => assert!(x.is_instance::<PyIndexError>(py)),
+            _ => panic!("Wrong error"),
+        }
+    })
 }
 
 /// Test definitions function of Circuit
@@ -484,23 +491,23 @@ fn test_get_slice() {
 fn test_definitions() {
     let added_op1 = Operation::from(DefinitionBit::new("ro".to_string(), 1, false));
     let added_op2 = Operation::from(InputSymbolic::new("test".to_string(), 1.0));
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
     let operation1 = convert_operation_to_pyobject(added_op1).unwrap();
     let operation2 = convert_operation_to_pyobject(added_op2).unwrap();
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation1.clone(),)).unwrap();
-    circuit.call_method1("add", (operation2.clone(),)).unwrap();
-
-    let comp_op = circuit.call_method0("definitions").unwrap();
-    let comparison = bool::extract(
-        comp_op
-            .call_method1("__eq__", (vec![operation1, operation2],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison)
+    pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation1.clone(),)).unwrap();
+        circuit.call_method1("add", (operation2.clone(),)).unwrap();
+
+        let comp_op = circuit.call_method0("definitions").unwrap();
+        let comparison = bool::extract(
+            comp_op
+                .call_method1("__eq__", (vec![operation1, operation2],))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison)
+    })
 }
 
 /// Test operations function of Circuit
@@ -508,23 +515,23 @@ fn test_definitions() {
 fn test_operations() {
     let added_op1 = Operation::from(RotateX::new(0, CalculatorFloat::from("theta")));
     let added_op2 = Operation::from(RotateZ::new(0, CalculatorFloat::from(0.0)));
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
     let operation1 = convert_operation_to_pyobject(added_op1).unwrap();
     let operation2 = convert_operation_to_pyobject(added_op2).unwrap();
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation1.clone(),)).unwrap();
-    circuit.call_method1("add", (operation2.clone(),)).unwrap();
-
-    let comp_op = circuit.call_method0("operations").unwrap();
-    let comparison = bool::extract(
-        comp_op
-            .call_method1("__eq__", (vec![operation1, operation2],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison)
+    pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation1.clone(),)).unwrap();
+        circuit.call_method1("add", (operation2.clone(),)).unwrap();
+
+        let comp_op = circuit.call_method0("operations").unwrap();
+        let comparison = bool::extract(
+            comp_op
+                .call_method1("__eq__", (vec![operation1, operation2],))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison)
+    })
 }
 
 /// Test filter_by_tag function of Circuit
@@ -532,47 +539,47 @@ fn test_operations() {
 fn test_filter_by_tag() {
     let added_op1 = Operation::from(DefinitionBit::new("ro".to_string(), 1, false));
     let added_op2 = Operation::from(InputSymbolic::new("test".to_string(), 1.0));
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
     let operation1 = convert_operation_to_pyobject(added_op1).unwrap();
     let operation2 = convert_operation_to_pyobject(added_op2).unwrap();
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation1.clone(),)).unwrap();
-    circuit.call_method1("add", (operation2.clone(),)).unwrap();
-    populate_circuit_rotatex(py, circuit, 0, 2);
+    pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation1.clone(),)).unwrap();
+        circuit.call_method1("add", (operation2.clone(),)).unwrap();
+        populate_circuit_rotatex(py, circuit, 0, 2);
 
-    let comp_op = circuit
-        .call_method1("filter_by_tag", ("Definition",))
+        let comp_op = circuit
+            .call_method1("filter_by_tag", ("Definition",))
+            .unwrap();
+        let comparison = bool::extract(
+            comp_op
+                .call_method1("__eq__", (vec![operation1, operation2],))
+                .unwrap(),
+        )
         .unwrap();
-    let comparison = bool::extract(
-        comp_op
-            .call_method1("__eq__", (vec![operation1, operation2],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        assert!(comparison);
 
-    let rotatex_type = py.get_type::<RotateXWrapper>();
-    let rotatex_0 = rotatex_type
-        .call1((0, 0))
-        .unwrap()
-        .cast_as::<PyCell<RotateXWrapper>>()
-        .unwrap();
-    let rotatex_1 = rotatex_type
-        .call1((1, 1))
-        .unwrap()
-        .cast_as::<PyCell<RotateXWrapper>>()
-        .unwrap();
+        let rotatex_type = py.get_type::<RotateXWrapper>();
+        let rotatex_0 = rotatex_type
+            .call1((0, 0))
+            .unwrap()
+            .cast_as::<PyCell<RotateXWrapper>>()
+            .unwrap();
+        let rotatex_1 = rotatex_type
+            .call1((1, 1))
+            .unwrap()
+            .cast_as::<PyCell<RotateXWrapper>>()
+            .unwrap();
 
-    let comp_op = circuit.call_method1("filter_by_tag", ("RotateX",)).unwrap();
-    let comparison = bool::extract(
-        comp_op
-            .call_method1("__eq__", (vec![rotatex_0, rotatex_1],))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison)
+        let comp_op = circuit.call_method1("filter_by_tag", ("RotateX",)).unwrap();
+        let comparison = bool::extract(
+            comp_op
+                .call_method1("__eq__", (vec![rotatex_0, rotatex_1],))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison)
+    })
 }
 
 /// Test add function
@@ -581,95 +588,95 @@ fn test_filter_by_tag() {
 #[test_case(Operation::from(SingleQubitGate::new(2, CalculatorFloat::from(0), CalculatorFloat::from("var"), CalculatorFloat::from(0), CalculatorFloat::from(0), CalculatorFloat::from(0), )); "SingleQubitGate float")]
 fn test_circuit_add_function(added_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(added_operation).unwrap();
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation.clone(),)).unwrap();
-
-    let comp_op = circuit.call_method1("__getitem__", (0,)).unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation,)).unwrap()).unwrap();
-    assert!(comparison);
-
-    let comparison = circuit.call_method1("add", (vec!["fails"],));
-    assert!(comparison.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(added_operation).unwrap();
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation.clone(),)).unwrap();
+
+        let comp_op = circuit.call_method1("__getitem__", (0,)).unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation,)).unwrap()).unwrap();
+        assert!(comparison);
+
+        let comparison = circuit.call_method1("add", (vec!["fails"],));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test the __repr__ and __format__ functions
 #[test]
 fn test_format_repr() {
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 2);
-    let format_repr = "RotateX(RotateX { qubit: 0, theta: Float(0.0) })\nRotateX(RotateX { qubit: 1, theta: Float(1.0) })\n";
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 2);
+        let format_repr = "RotateX(RotateX { qubit: 0, theta: Float(0.0) })\nRotateX(RotateX { qubit: 1, theta: Float(1.0) })\n";
 
-    let to_format = circuit.call_method1("__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format).unwrap();
+        let to_format = circuit.call_method1("__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format).unwrap();
 
-    let to_repr = circuit.call_method0("__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr).unwrap();
+        let to_repr = circuit.call_method0("__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr).unwrap();
 
-    assert_eq!(format_op, format_repr);
-    assert_eq!(repr_op, format_repr);
+        assert_eq!(format_op, format_repr);
+        assert_eq!(repr_op, format_repr);
+    })
 }
 
 /// Test fmt::Debug for OperationIteratorWrapper
 #[test]
 fn test_fmt_circuititerator() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let new_circuit = new_circuit(py);
-    populate_circuit_rotatex(py, new_circuit, 0, 2);
-    let circuit_iter = new_circuit
-        .call_method0("__iter__")
-        .unwrap()
-        .cast_as::<PyCell<OperationIteratorWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let new_circuit = new_circuit(py);
+        populate_circuit_rotatex(py, new_circuit, 0, 2);
+        let circuit_iter = new_circuit
+            .call_method0("__iter__")
+            .unwrap()
+            .cast_as::<PyCell<OperationIteratorWrapper>>()
+            .unwrap();
 
-    let fmt = "RefCell { value: OperationIteratorWrapper { internal: OperationIterator { definition_iter: IntoIter([]), operation_iter: IntoIter([RotateX(RotateX { qubit: 0, theta: Float(0.0) }), RotateX(RotateX { qubit: 1, theta: Float(1.0) })]) } } }";
+        let fmt = "RefCell { value: OperationIteratorWrapper { internal: OperationIterator { definition_iter: IntoIter([]), operation_iter: IntoIter([RotateX(RotateX { qubit: 0, theta: Float(0.0) }), RotateX(RotateX { qubit: 1, theta: Float(1.0) })]) } } }";
 
-    assert_eq!(format!("{:?}", circuit_iter), fmt);
+        assert_eq!(format!("{:?}", circuit_iter), fmt);
+    })
 }
 
 /// Test the __richcmp__ function
 #[test]
 fn test_richcmp() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit_one = new_circuit(py);
-    populate_circuit_rotatex(py, circuit_one, 0, 2);
-    let circuit_two = new_circuit(py);
-    populate_circuit_rotatex(py, circuit_two, 0, 3);
-    let operation1 = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
-
-    let comparison =
-        bool::extract(circuit_one.call_method1("__eq__", (circuit_two,)).unwrap()).unwrap();
-    assert!(!comparison);
-    let comparison = bool::extract(
-        circuit_one
-            .call_method1("__eq__", (operation1.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(!comparison);
-
-    let comparison =
-        bool::extract(circuit_one.call_method1("__ne__", (circuit_two,)).unwrap()).unwrap();
-    assert!(comparison);
-    let comparison = bool::extract(
-        circuit_one
-            .call_method1("__ne__", (operation1.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let comparison = circuit_one.call_method1("__ge__", (operation1,));
-    assert!(comparison.is_err());
+    Python::with_gil(|py| -> () {
+        let circuit_one = new_circuit(py);
+        populate_circuit_rotatex(py, circuit_one, 0, 2);
+        let circuit_two = new_circuit(py);
+        populate_circuit_rotatex(py, circuit_two, 0, 3);
+        let operation1 = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
+
+        let comparison =
+            bool::extract(circuit_one.call_method1("__eq__", (circuit_two,)).unwrap()).unwrap();
+        assert!(!comparison);
+        let comparison = bool::extract(
+            circuit_one
+                .call_method1("__eq__", (operation1.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(!comparison);
+
+        let comparison =
+            bool::extract(circuit_one.call_method1("__ne__", (circuit_two,)).unwrap()).unwrap();
+        assert!(comparison);
+        let comparison = bool::extract(
+            circuit_one
+                .call_method1("__ne__", (operation1.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+
+        let comparison = circuit_one.call_method1("__ge__", (operation1,));
+        assert!(comparison.is_err());
+    })
 }
 
 #[test]
@@ -677,41 +684,43 @@ fn test_circuit_iadd_magic_method() {
     let added_op1 = Operation::from(DefinitionBit::new("ro".to_string(), 1, false));
     let added_op2 = Operation::from(RotateX::new(0, CalculatorFloat::from(1.0)));
     let added_op3 = Operation::from(PauliX::new(0));
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
     let operation1 = convert_operation_to_pyobject(added_op1).unwrap();
     let operation2 = convert_operation_to_pyobject(added_op2).unwrap();
     let operation3 = convert_operation_to_pyobject(added_op3).unwrap();
+    pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let added_circuit = new_circuit(py);
+        added_circuit
+            .call_method1("add", (operation3.clone(),))
+            .unwrap();
 
-    let added_circuit = new_circuit(py);
-    added_circuit
-        .call_method1("add", (operation3.clone(),))
-        .unwrap();
-
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation1.clone(),)).unwrap();
-    circuit
-        .call_method1("__iadd__", (operation2.clone(),))
-        .unwrap();
-    circuit
-        .call_method1("__iadd__", (added_circuit.clone(),))
-        .unwrap();
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation1.clone(),)).unwrap();
+        circuit
+            .call_method1("__iadd__", (operation2.clone(),))
+            .unwrap();
+        circuit
+            .call_method1("__iadd__", (added_circuit.clone(),))
+            .unwrap();
 
-    let comp_op = circuit.call_method1("__getitem__", (0,)).unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation1,)).unwrap()).unwrap();
-    assert!(comparison);
+        let comp_op = circuit.call_method1("__getitem__", (0,)).unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation1,)).unwrap()).unwrap();
+        assert!(comparison);
 
-    let comp_op = circuit.call_method1("__getitem__", (1,)).unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation2,)).unwrap()).unwrap();
-    assert!(comparison);
+        let comp_op = circuit.call_method1("__getitem__", (1,)).unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation2,)).unwrap()).unwrap();
+        assert!(comparison);
 
-    let comp_op = circuit.call_method1("__getitem__", (2,)).unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation3,)).unwrap()).unwrap();
-    assert!(comparison);
+        let comp_op = circuit.call_method1("__getitem__", (2,)).unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation3,)).unwrap()).unwrap();
+        assert!(comparison);
 
-    let comparison = circuit.call_method1("__iadd__", (vec!["fails"],));
-    assert!(comparison.is_err());
+        let comparison = circuit.call_method1("__iadd__", (vec!["fails"],));
+        assert!(comparison.is_err());
+    })
 }
 
 #[test]
@@ -719,161 +728,168 @@ fn test_circuit_add_magic_method() {
     let added_op1 = Operation::from(DefinitionBit::new("ro".to_string(), 1, false));
     let added_op2 = Operation::from(RotateX::new(0, CalculatorFloat::from(1.0)));
     let added_op3 = Operation::from(PauliX::new(0));
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
     let operation1 = convert_operation_to_pyobject(added_op1).unwrap();
     let operation2 = convert_operation_to_pyobject(added_op2).unwrap();
     let operation3 = convert_operation_to_pyobject(added_op3).unwrap();
+    pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let added_circuit = new_circuit(py);
+        added_circuit
+            .call_method1("add", (operation3.clone(),))
+            .unwrap();
 
-    let added_circuit = new_circuit(py);
-    added_circuit
-        .call_method1("add", (operation3.clone(),))
-        .unwrap();
-
-    let circuit = new_circuit(py);
-    circuit.call_method1("add", (operation1.clone(),)).unwrap();
-    let circuit1 = circuit
-        .call_method1("__add__", (operation2.clone(),))
-        .unwrap();
-    let circuit2 = circuit1
-        .call_method1("__add__", (added_circuit.clone(),))
-        .unwrap();
+        let circuit = new_circuit(py);
+        circuit.call_method1("add", (operation1.clone(),)).unwrap();
+        let circuit1 = circuit
+            .call_method1("__add__", (operation2.clone(),))
+            .unwrap();
+        let circuit2 = circuit1
+            .call_method1("__add__", (added_circuit.clone(),))
+            .unwrap();
 
-    let comp_op = circuit2.call_method1("__getitem__", (0,)).unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation1,)).unwrap()).unwrap();
-    assert!(comparison);
+        let comp_op = circuit2.call_method1("__getitem__", (0,)).unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation1,)).unwrap()).unwrap();
+        assert!(comparison);
 
-    let comp_op = circuit2.call_method1("__getitem__", (1,)).unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation2,)).unwrap()).unwrap();
-    assert!(comparison);
+        let comp_op = circuit2.call_method1("__getitem__", (1,)).unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation2,)).unwrap()).unwrap();
+        assert!(comparison);
 
-    let comp_op = circuit2.call_method1("__getitem__", (2,)).unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation3,)).unwrap()).unwrap();
-    assert!(comparison);
+        let comp_op = circuit2.call_method1("__getitem__", (2,)).unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation3,)).unwrap()).unwrap();
+        assert!(comparison);
 
-    let comparison = circuit.call_method1("__add__", (vec!["fails"],));
-    assert!(comparison.is_err());
+        let comparison = circuit.call_method1("__add__", (vec!["fails"],));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test iterator interface of Circuit
 #[test]
 fn test_iter() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let new_circuit = new_circuit(py);
-    populate_circuit_rotatex(py, new_circuit, 0, 3);
-
-    let rotatex_type = py.get_type::<RotateXWrapper>();
-    let new_rotatex_0 = rotatex_type
-        .call1((0, 0))
-        .unwrap()
-        .cast_as::<PyCell<RotateXWrapper>>()
-        .unwrap();
-    let new_rotatex_1 = rotatex_type
-        .call1((1, 1))
-        .unwrap()
-        .cast_as::<PyCell<RotateXWrapper>>()
-        .unwrap();
-    let new_rotatex_2 = rotatex_type
-        .call1((2, 2))
-        .unwrap()
-        .cast_as::<PyCell<RotateXWrapper>>()
-        .unwrap();
-    let comparison_vec = vec![new_rotatex_0, new_rotatex_1, new_rotatex_2];
+    Python::with_gil(|py| -> () {
+        let new_circuit = new_circuit(py);
+        populate_circuit_rotatex(py, new_circuit, 0, 3);
+
+        let rotatex_type = py.get_type::<RotateXWrapper>();
+        let new_rotatex_0 = rotatex_type
+            .call1((0, 0))
+            .unwrap()
+            .cast_as::<PyCell<RotateXWrapper>>()
+            .unwrap();
+        let new_rotatex_1 = rotatex_type
+            .call1((1, 1))
+            .unwrap()
+            .cast_as::<PyCell<RotateXWrapper>>()
+            .unwrap();
+        let new_rotatex_2 = rotatex_type
+            .call1((2, 2))
+            .unwrap()
+            .cast_as::<PyCell<RotateXWrapper>>()
+            .unwrap();
+        let comparison_vec = vec![new_rotatex_0, new_rotatex_1, new_rotatex_2];
 
-    let t = new_circuit
-        .call_method0("__iter__")
-        .unwrap()
-        .cast_as::<PyCell<OperationIteratorWrapper>>()
-        .unwrap();
+        let t = new_circuit
+            .call_method0("__iter__")
+            .unwrap()
+            .cast_as::<PyCell<OperationIteratorWrapper>>()
+            .unwrap();
 
-    for i in 0..3 {
-        let comp_op = t.call_method0("__next__").unwrap();
-        let comparison = bool::extract(
-            comp_op
-                .call_method1("__eq__", (comparison_vec[i],))
-                .unwrap(),
-        )
-        .unwrap();
-        assert!(comparison)
-    }
+        for i in 0..3 {
+            let comp_op = t.call_method0("__next__").unwrap();
+            let comparison = bool::extract(
+                comp_op
+                    .call_method1("__eq__", (comparison_vec[i],))
+                    .unwrap(),
+            )
+            .unwrap();
+            assert!(comparison)
+        }
 
-    let iter_op = t.call_method0("__iter__").unwrap();
-    let comparison = bool::extract(iter_op.call_method1("__eq__", (t,)).unwrap()).unwrap();
-    assert!(comparison);
+        let iter_op = t.call_method0("__iter__").unwrap();
+        let comparison = bool::extract(iter_op.call_method1("__eq__", (t,)).unwrap()).unwrap();
+        assert!(comparison);
+    })
 }
 
 /// Test the __len__ function
 #[test]
 fn test_len() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 5);
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 5);
 
-    let len_op: usize = usize::extract(circuit.call_method0("__len__").unwrap()).unwrap();
-    assert_eq!(len_op, 5_usize);
+        let len_op: usize = usize::extract(circuit.call_method0("__len__").unwrap()).unwrap();
+        assert_eq!(len_op, 5_usize);
+    })
 }
 
 ///  Test single index set and write access using "__getitem__" function
 #[test]
 fn test_single_index_access_getitem() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
-    populate_circuit_rotatex(py, circuit, 0, 3);
-
-    // test access at index 1
-    let comp_op = circuit.call_method1("__getitem__", (1,)).unwrap();
-    let operation =
-        convert_operation_to_pyobject(Operation::from(RotateX::new(1, CalculatorFloat::from(1))))
-            .unwrap();
-    let comparison = bool::extract(comp_op.call_method1("__eq__", (operation,)).unwrap()).unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
+        populate_circuit_rotatex(py, circuit, 0, 3);
+
+        // test access at index 1
+        let comp_op = circuit.call_method1("__getitem__", (1,)).unwrap();
+        let operation = convert_operation_to_pyobject(Operation::from(RotateX::new(
+            1,
+            CalculatorFloat::from(1),
+        )))
+        .unwrap();
+        let comparison =
+            bool::extract(comp_op.call_method1("__eq__", (operation,)).unwrap()).unwrap();
+        assert!(comparison);
+
+        // test setting new operation at index 1
+        let operation2 = convert_operation_to_pyobject(Operation::from(RotateX::new(
+            1,
+            CalculatorFloat::from(10),
+        )))
+        .unwrap();
 
-    // test setting new operation at index 1
-    let operation2 =
-        convert_operation_to_pyobject(Operation::from(RotateX::new(1, CalculatorFloat::from(10))))
+        circuit
+            .call_method1("__setitem__", (1, operation2.clone()))
             .unwrap();
 
-    circuit
-        .call_method1("__setitem__", (1, operation2.clone()))
+        let comp_op = circuit.call_method1("__getitem__", (1,)).unwrap();
+        let comparison = bool::extract(
+            comp_op
+                .call_method1("__eq__", (operation2.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comp_op = circuit.call_method1("__getitem__", (1,)).unwrap();
-    let comparison = bool::extract(
-        comp_op
-            .call_method1("__eq__", (operation2.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        let comparison = circuit.call_method1("__setitem__", (1, vec!["fails"]));
+        assert!(comparison.is_err());
 
-    let comparison = circuit.call_method1("__setitem__", (1, vec!["fails"]));
-    assert!(comparison.is_err());
+        let comparison = circuit.call_method1("__getitem__", (20,));
+        assert!(comparison.is_err());
 
-    let comparison = circuit.call_method1("__getitem__", (20,));
-    assert!(comparison.is_err());
-
-    let comparison = circuit.call_method1("__setitem__", (3, operation2));
-    assert!(comparison.is_err());
+        let comparison = circuit.call_method1("__setitem__", (3, operation2));
+        assert!(comparison.is_err());
+    })
 }
 
 #[test]
 fn test_convert_into_circuit() {
     let added_op = Operation::from(PauliX::new(0));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(added_op).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(added_op).unwrap();
 
-    let added_circuit = new_circuit(py);
-    let comparison = added_circuit.call_method1("convert_into_circuit", (operation,));
-    assert!(comparison.is_err());
+        let added_circuit = new_circuit(py);
+        let comparison = added_circuit.call_method1("convert_into_circuit", (operation,));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test function overrotate() for Circuit
@@ -881,46 +897,46 @@ fn test_convert_into_circuit() {
 // #[cfg(feature = "overrotate")]
 fn test_circuit_overrotate() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let circuit = new_circuit(py);
+    Python::with_gil(|py| -> () {
+        let circuit = new_circuit(py);
 
-    let overrotation_type = py.get_type::<PragmaOverrotationWrapper>();
-    let _new_overrotation_1 = overrotation_type
-        .call1(("RotateY".to_string(), vec![1], 20.0, 30.0))
-        .unwrap();
-    circuit.call_method1("add", (_new_overrotation_1,)).unwrap();
+        let overrotation_type = py.get_type::<PragmaOverrotationWrapper>();
+        let _new_overrotation_1 = overrotation_type
+            .call1(("RotateY".to_string(), vec![1], 20.0, 30.0))
+            .unwrap();
+        circuit.call_method1("add", (_new_overrotation_1,)).unwrap();
 
-    let rotatex_type = py.get_type::<RotateXWrapper>();
-    let new_rotatex_0 = rotatex_type.call1((0, 0.0)).unwrap();
-    circuit.call_method1("add", (new_rotatex_0,)).unwrap();
+        let rotatex_type = py.get_type::<RotateXWrapper>();
+        let new_rotatex_0 = rotatex_type.call1((0, 0.0)).unwrap();
+        circuit.call_method1("add", (new_rotatex_0,)).unwrap();
 
-    let rotatey_type = py.get_type::<RotateYWrapper>();
-    let new_rotatey_0 = rotatey_type.call1((0, 1.0)).unwrap();
-    circuit.call_method1("add", (new_rotatey_0,)).unwrap();
+        let rotatey_type = py.get_type::<RotateYWrapper>();
+        let new_rotatey_0 = rotatey_type.call1((0, 1.0)).unwrap();
+        circuit.call_method1("add", (new_rotatey_0,)).unwrap();
 
-    let new_rotatey_1 = rotatey_type.call1((1, 2.0)).unwrap();
-    circuit.call_method1("add", (new_rotatey_1,)).unwrap();
-    let new_rotatey_1 = rotatey_type.call1((1, 3.0)).unwrap();
-    circuit.call_method1("add", (new_rotatey_1,)).unwrap();
+        let new_rotatey_1 = rotatey_type.call1((1, 2.0)).unwrap();
+        circuit.call_method1("add", (new_rotatey_1,)).unwrap();
+        let new_rotatey_1 = rotatey_type.call1((1, 3.0)).unwrap();
+        circuit.call_method1("add", (new_rotatey_1,)).unwrap();
 
-    let circuit_overrotated = circuit
-        .call_method0("overrotate")
-        .unwrap()
-        .cast_as::<PyCell<CircuitWrapper>>()
-        .unwrap();
+        let circuit_overrotated = circuit
+            .call_method0("overrotate")
+            .unwrap()
+            .cast_as::<PyCell<CircuitWrapper>>()
+            .unwrap();
 
-    assert_ne!(
-        format!("{:?}", circuit.clone()),
-        format!("{:?}", circuit_overrotated.clone())
-    );
+        assert_ne!(
+            format!("{:?}", circuit.clone()),
+            format!("{:?}", circuit_overrotated.clone())
+        );
 
-    let comparison = bool::extract(
-        circuit
-            .as_ref()
-            .call_method1("__ne__", (circuit_overrotated,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        let comparison = bool::extract(
+            circuit
+                .as_ref()
+                .call_method1("__ne__", (circuit_overrotated,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
diff --git a/qoqo/tests/integration/measurements/cheated_basis_rotation_measurement.rs b/qoqo/tests/integration/measurements/cheated_basis_rotation_measurement.rs
index 9e34f772..de1aef34 100644
--- a/qoqo/tests/integration/measurements/cheated_basis_rotation_measurement.rs
+++ b/qoqo/tests/integration/measurements/cheated_basis_rotation_measurement.rs
@@ -66,281 +66,273 @@ fn test_returning_circuits() {
 #[test]
 fn test_py03_evaluate_bool() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_0",))
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_1",))
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_2",))
+            .unwrap();
+
+        let mut linear_map: HashMap<usize, f64> = HashMap::new();
+        linear_map.insert(0, 3.0);
+        let _ = input
+            .call_method1("add_linear_exp_val", ("single_pp_val", linear_map))
+            .unwrap();
+        let mut linear_map: HashMap<usize, f64> = HashMap::new();
+        linear_map.insert(0, 4.0);
+        linear_map.insert(1, 5.0);
+        linear_map.insert(2, 6.0);
+        let _ = input
+            .call_method1("add_linear_exp_val", ("multi_pp_val", linear_map))
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_0",))
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_1",))
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_2",))
-        .unwrap();
-
-    let mut linear_map: HashMap<usize, f64> = HashMap::new();
-    linear_map.insert(0, 3.0);
-    let _ = input
-        .call_method1("add_linear_exp_val", ("single_pp_val", linear_map))
-        .unwrap();
-    let mut linear_map: HashMap<usize, f64> = HashMap::new();
-    linear_map.insert(0, 4.0);
-    linear_map.insert(1, 5.0);
-    linear_map.insert(2, 6.0);
-    let _ = input
-        .call_method1("add_linear_exp_val", ("multi_pp_val", linear_map))
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-
-    let mut measured_registers: HashMap<String, FloatOutputRegister> = HashMap::new();
-    let _ = measured_registers.insert("ro_pauli_product_0".to_string(), vec![vec![1.0]]);
-    let _ = measured_registers.insert("ro_pauli_product_1".to_string(), vec![vec![0.0]]);
-    let _ = measured_registers.insert("ro_pauli_product_2".to_string(), vec![vec![-0.5]]);
-
-    let bit_register: HashMap<String, BitOutputRegister> = HashMap::new();
-    let complex_register: HashMap<String, ComplexOutputRegister> = HashMap::new();
-    let result = br
-        .call_method1(
-            "evaluate",
-            (bit_register, measured_registers, complex_register),
-        )
-        .unwrap();
-    let two_qubit_exp_val_py = f64::extract(result.get_item("single_pp_val").unwrap()).unwrap();
-    let two_pp_exp_val_py = f64::extract(result.get_item("multi_pp_val").unwrap()).unwrap();
-    assert_eq!(two_qubit_exp_val_py, 3.0);
-    assert_eq!(two_pp_exp_val_py, 1.0);
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+
+        let mut measured_registers: HashMap<String, FloatOutputRegister> = HashMap::new();
+        let _ = measured_registers.insert("ro_pauli_product_0".to_string(), vec![vec![1.0]]);
+        let _ = measured_registers.insert("ro_pauli_product_1".to_string(), vec![vec![0.0]]);
+        let _ = measured_registers.insert("ro_pauli_product_2".to_string(), vec![vec![-0.5]]);
+
+        let bit_register: HashMap<String, BitOutputRegister> = HashMap::new();
+        let complex_register: HashMap<String, ComplexOutputRegister> = HashMap::new();
+        let result = br
+            .call_method1(
+                "evaluate",
+                (bit_register, measured_registers, complex_register),
+            )
+            .unwrap();
+        let two_qubit_exp_val_py = f64::extract(result.get_item("single_pp_val").unwrap()).unwrap();
+        let two_pp_exp_val_py = f64::extract(result.get_item("multi_pp_val").unwrap()).unwrap();
+        assert_eq!(two_qubit_exp_val_py, 3.0);
+        assert_eq!(two_pp_exp_val_py, 1.0);
+    })
 }
 
 /// Test evaluate() function for CheatedBasisRotation measurement with symbolic parameters
 #[test]
 fn test_evaluate_symbolic() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_0",))
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_1",))
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_2",))
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_0",))
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_1",))
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_2",))
-        .unwrap();
-
-    let symbolic_pystring = "sin(3.0 * pauli_product_0) + sin(-1.0 * pauli_product_1)".to_string();
-    let _ = input
-        .call_method1("add_symbolic_exp_val", ("single_pp_val", symbolic_pystring))
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-
-    let mut measured_registers: HashMap<String, FloatOutputRegister> = HashMap::new();
-    let _ = measured_registers.insert("ro_pauli_product_0".to_string(), vec![vec![1.0]]);
-    let _ = measured_registers.insert("ro_pauli_product_1".to_string(), vec![vec![-1.0]]);
-    let _ = measured_registers.insert("ro_pauli_product_2".to_string(), vec![vec![-0.5]]);
-
-    let bit_register: HashMap<String, BitOutputRegister> = HashMap::new();
-    let complex_register: HashMap<String, ComplexOutputRegister> = HashMap::new();
-    let result = br
-        .call_method1(
-            "evaluate",
-            (bit_register, measured_registers, complex_register),
-        )
-        .unwrap();
-    let single_pp_val_py = f64::extract(result.get_item("single_pp_val").unwrap()).unwrap();
-    assert!((single_pp_val_py - (3.0_f64.sin() + 1.0_f64.sin())).abs() < f64::EPSILON);
+        let symbolic_pystring =
+            "sin(3.0 * pauli_product_0) + sin(-1.0 * pauli_product_1)".to_string();
+        let _ = input
+            .call_method1("add_symbolic_exp_val", ("single_pp_val", symbolic_pystring))
+            .unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+
+        let mut measured_registers: HashMap<String, FloatOutputRegister> = HashMap::new();
+        let _ = measured_registers.insert("ro_pauli_product_0".to_string(), vec![vec![1.0]]);
+        let _ = measured_registers.insert("ro_pauli_product_1".to_string(), vec![vec![-1.0]]);
+        let _ = measured_registers.insert("ro_pauli_product_2".to_string(), vec![vec![-0.5]]);
+
+        let bit_register: HashMap<String, BitOutputRegister> = HashMap::new();
+        let complex_register: HashMap<String, ComplexOutputRegister> = HashMap::new();
+        let result = br
+            .call_method1(
+                "evaluate",
+                (bit_register, measured_registers, complex_register),
+            )
+            .unwrap();
+        let single_pp_val_py = f64::extract(result.get_item("single_pp_val").unwrap()).unwrap();
+        assert!((single_pp_val_py - (3.0_f64.sin() + 1.0_f64.sin())).abs() < f64::EPSILON);
+    })
 }
 
 /// Test evaluate failure
 #[test]
 fn test_py03_evaluate_error0() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_0",))
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_1",))
+            .unwrap();
+        let _ = input
+            .call_method1("add_pauli_product", ("ro_pauli_product_2",))
+            .unwrap();
+
+        let symbolic_pystring =
+            "sin(3.0 * pauli_product_0) + sin(-1.0 * pauli_product_3)".to_string();
+        let _ = input
+            .call_method1("add_symbolic_exp_val", ("single_pp_val", symbolic_pystring))
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_0",))
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_1",))
-        .unwrap();
-    let _ = input
-        .call_method1("add_pauli_product", ("ro_pauli_product_2",))
-        .unwrap();
-
-    let symbolic_pystring = "sin(3.0 * pauli_product_0) + sin(-1.0 * pauli_product_3)".to_string();
-    let _ = input
-        .call_method1("add_symbolic_exp_val", ("single_pp_val", symbolic_pystring))
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-
-    let input2: HashMap<String, FloatOutputRegister> =
-        HashMap::<String, FloatOutputRegister>::new();
-    let input3: HashMap<String, ComplexOutputRegister> =
-        HashMap::<String, ComplexOutputRegister>::new();
-
-    let result = br.call_method1("evaluate", (vec![0], input2.clone(), input3.clone()));
-    assert!(result.is_err());
-
-    let mut input1: HashMap<String, Vec<Vec<usize>>> = HashMap::new();
-    input1.insert("ro".to_string(), vec![vec![0]]);
-    let error = br.call_method1("evaluate", (input1, input2, input3));
-    assert!(error.is_err());
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+
+        let input2: HashMap<String, FloatOutputRegister> =
+            HashMap::<String, FloatOutputRegister>::new();
+        let input3: HashMap<String, ComplexOutputRegister> =
+            HashMap::<String, ComplexOutputRegister>::new();
+
+        let result = br.call_method1("evaluate", (vec![0], input2.clone(), input3.clone()));
+        assert!(result.is_err());
+
+        let mut input1: HashMap<String, Vec<Vec<usize>>> = HashMap::new();
+        input1.insert("ro".to_string(), vec![vec![0]]);
+        let error = br.call_method1("evaluate", (input1, input2, input3));
+        assert!(error.is_err());
+    })
 }
 
 /// Test copy
 #[test]
 fn test_pyo3_copy() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
+        circs.push(circ1);
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+        let br_clone = br.clone();
+
+        let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
+        let circuits_clone: Vec<CircuitWrapper> = br_clone
+            .call_method0("circuits")
+            .unwrap()
+            .extract()
+            .unwrap();
+        assert_eq!(circuits, circuits_clone);
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
-    circs.push(circ1);
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-    let br_clone = br.clone();
-
-    let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
-    let circuits_clone: Vec<CircuitWrapper> = br_clone
-        .call_method0("circuits")
-        .unwrap()
-        .extract()
-        .unwrap();
-    assert_eq!(circuits, circuits_clone);
-
-    let const_circuit: CircuitWrapper = br
-        .call_method0("constant_circuit")
-        .unwrap()
-        .extract()
-        .unwrap();
-    let const_circuit_clone: CircuitWrapper = br_clone
-        .call_method0("constant_circuit")
-        .unwrap()
-        .extract()
-        .unwrap();
-    assert_eq!(const_circuit, const_circuit_clone);
+        let const_circuit: CircuitWrapper = br
+            .call_method0("constant_circuit")
+            .unwrap()
+            .extract()
+            .unwrap();
+        let const_circuit_clone: CircuitWrapper = br_clone
+            .call_method0("constant_circuit")
+            .unwrap()
+            .extract()
+            .unwrap();
+        assert_eq!(const_circuit, const_circuit_clone);
+    })
 }
 
 /// Test debug and clone
 #[test]
 fn test_pyo3_debug() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-    let br_wrapper = br.extract::<CheatedBasisRotationWrapper>().unwrap();
-
-    let br_clone = br_wrapper.clone();
-    assert_eq!(format!("{:?}", br_wrapper), format!("{:?}", br_clone));
-
-    let debug_string = "RefCell { value: CheatedBasisRotationWrapper { internal: CheatedBasisRotation { constant_circuit: Some(Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }), circuits: [Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }], input: CheatedBasisRotationInput { measured_exp_vals: {}, pauli_product_keys: {\"ro\": 0} } } } }";
-    assert_eq!(format!("{:?}", br), debug_string);
-
-    let debug_input = input.clone();
-    let debug_input_string = "RefCell { value: CheatedBasisRotationInputWrapper { internal: CheatedBasisRotationInput { measured_exp_vals: {}, pauli_product_keys: {\"ro\": 0} } } }";
-    assert_eq!(format!("{:?}", input), debug_input_string);
-    assert_eq!(
-        CheatedBasisRotationInputWrapper::default().internal,
-        CheatedBasisRotationInputWrapper::new().internal
-    );
-
-    let mut linear_map: HashMap<usize, f64> = HashMap::new();
-    linear_map.insert(0, 3.0);
-    let _ = debug_input
-        .call_method1("add_linear_exp_val", ("single_pp_val", linear_map.clone()))
-        .unwrap();
-    linear_map.insert(0, 5.0);
-    let error = debug_input.call_method1("add_linear_exp_val", ("single_pp_val", linear_map));
-    assert!(error.is_err());
-
-    let symbolic_pystring = "sin(3.0 * pauli_product_1)".to_string();
-    let error =
-        debug_input.call_method1("add_symbolic_exp_val", ("single_pp_val", symbolic_pystring));
-    assert!(error.is_err());
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+        let br_wrapper = br.extract::<CheatedBasisRotationWrapper>().unwrap();
+
+        let br_clone = br_wrapper.clone();
+        assert_eq!(format!("{:?}", br_wrapper), format!("{:?}", br_clone));
+
+        let debug_string = "RefCell { value: CheatedBasisRotationWrapper { internal: CheatedBasisRotation { constant_circuit: Some(Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }), circuits: [Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }], input: CheatedBasisRotationInput { measured_exp_vals: {}, pauli_product_keys: {\"ro\": 0} } } } }";
+        assert_eq!(format!("{:?}", br), debug_string);
+
+        let debug_input = input.clone();
+        let debug_input_string = "RefCell { value: CheatedBasisRotationInputWrapper { internal: CheatedBasisRotationInput { measured_exp_vals: {}, pauli_product_keys: {\"ro\": 0} } } }";
+        assert_eq!(format!("{:?}", input), debug_input_string);
+        assert_eq!(
+            CheatedBasisRotationInputWrapper::default().internal,
+            CheatedBasisRotationInputWrapper::new().internal
+        );
+
+        let mut linear_map: HashMap<usize, f64> = HashMap::new();
+        linear_map.insert(0, 3.0);
+        let _ = debug_input
+            .call_method1("add_linear_exp_val", ("single_pp_val", linear_map.clone()))
+            .unwrap();
+        linear_map.insert(0, 5.0);
+        let error = debug_input.call_method1("add_linear_exp_val", ("single_pp_val", linear_map));
+        assert!(error.is_err());
+
+        let symbolic_pystring = "sin(3.0 * pauli_product_1)".to_string();
+        let error =
+            debug_input.call_method1("add_symbolic_exp_val", ("single_pp_val", symbolic_pystring));
+        assert!(error.is_err());
+    })
 }
 
 /// Test _internal_to_bincode function
@@ -391,119 +383,113 @@ fn test_internal_to_bincode() {
 #[test]
 fn test_to_from_json() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+
+        let new_br = br.clone();
+        let serialised = br.call_method0("to_json").unwrap();
+        let deserialised = new_br
+            .call_method1("from_json", (serialised,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+        assert_eq!(format!("{:?}", br), format!("{:?}", deserialised));
+
+        let deserialised_error =
+            new_br.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
+        assert!(deserialised_error.is_err());
+
+        let deserialised_error =
+            new_br.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-
-    let new_br = br.clone();
-    let serialised = br.call_method0("to_json").unwrap();
-    let deserialised = new_br
-        .call_method1("from_json", (serialised,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-    assert_eq!(format!("{:?}", br), format!("{:?}", deserialised));
-
-    let deserialised_error =
-        new_br.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
-    assert!(deserialised_error.is_err());
-
-    let deserialised_error =
-        new_br.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
-    assert!(deserialised_error.is_err());
-
-    let serialised_error = serialised.call_method0("to_json");
-    assert!(serialised_error.is_err());
+        let serialised_error = serialised.call_method0("to_json");
+        assert!(serialised_error.is_err());
+    })
 }
 
 /// Test substitute_parameters
 #[test]
 fn test_substitute_parameters() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
-    circs.push(circ1);
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-
-    let mut map: HashMap<String, f64> = HashMap::<String, f64>::new();
-    map.insert("theta".to_string(), 0.0);
-    let br_sub = br
-        .call_method1("substitute_parameters", (map,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-
-    let br_wrapper = br.extract::<CheatedBasisRotationWrapper>().unwrap();
-    let br_sub_wrapper = br_sub.extract::<CheatedBasisRotationWrapper>().unwrap();
-    assert_ne!(format!("{:?}", br_wrapper), format!("{:?}", br_sub_wrapper));
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
+        circs.push(circ1);
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+
+        let mut map: HashMap<String, f64> = HashMap::<String, f64>::new();
+        map.insert("theta".to_string(), 0.0);
+        let br_sub = br
+            .call_method1("substitute_parameters", (map,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+
+        let br_wrapper = br.extract::<CheatedBasisRotationWrapper>().unwrap();
+        let br_sub_wrapper = br_sub.extract::<CheatedBasisRotationWrapper>().unwrap();
+        assert_ne!(format!("{:?}", br_wrapper), format!("{:?}", br_sub_wrapper));
+    })
 }
 
 /// Test substitute_parameters returning an error
 #[test]
 fn test_substitute_parameters_error() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input.call_method1("add_pauli_product", ("ro",)).unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
-    circs.push(circ1);
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
-
-    let map: HashMap<String, f64> = HashMap::<String, f64>::new();
-    let br_sub = br.call_method1("substitute_parameters", (map,));
-    assert!(br_sub.is_err());
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
+        circs.push(circ1);
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
+
+        let map: HashMap<String, f64> = HashMap::<String, f64>::new();
+        let br_sub = br.call_method1("substitute_parameters", (map,));
+        assert!(br_sub.is_err());
+    })
 }
diff --git a/qoqo/tests/integration/measurements/cheated_measurement.rs b/qoqo/tests/integration/measurements/cheated_measurement.rs
index edc8a2a8..32c01404 100644
--- a/qoqo/tests/integration/measurements/cheated_measurement.rs
+++ b/qoqo/tests/integration/measurements/cheated_measurement.rs
@@ -29,39 +29,37 @@ use test_case::test_case;
 #[test]
 fn test_returning_circuits() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input = input_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
+        circs.push(circ1);
+        let br_type = py.get_type::<CheatedWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input = input_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
-    circs.push(circ1);
-    let br_type = py.get_type::<CheatedWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-
-    let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
-    for (index, b) in circuits.iter().enumerate() {
-        assert_eq!(b, circs.get(index).unwrap());
-    }
-    let const_circuit: CircuitWrapper = br
-        .call_method0("constant_circuit")
-        .unwrap()
-        .extract()
-        .unwrap();
-    assert_eq!(CircuitWrapper::new(), const_circuit);
+        let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
+        for (index, b) in circuits.iter().enumerate() {
+            assert_eq!(b, circs.get(index).unwrap());
+        }
+        let const_circuit: CircuitWrapper = br
+            .call_method0("constant_circuit")
+            .unwrap()
+            .extract()
+            .unwrap();
+        assert_eq!(CircuitWrapper::new(), const_circuit);
+    })
 }
 
 /// Test evaluate() function for Cheated measurement
@@ -77,249 +75,244 @@ fn test_py03_evaluate_bool(
     value_off_diagonal: f64,
 ) {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input = input_type
+            .call1((1,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(1.0, 0.0)),
+            (0, 1, Complex64::new(0.0, 0.0)),
+            (1, 0, Complex64::new(0.0, 0.0)),
+            (1, 1, Complex64::new(-1.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(0.0, 0.0)),
+            (0, 1, Complex64::new(0.0, -1.0)),
+            (1, 0, Complex64::new(0.0, 1.0)),
+            (1, 1, Complex64::new(0.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1(
+                "add_operator_exp_val",
+                ("test_off_diagonal", test_matrix, "ro"),
+            )
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input = input_type
-        .call1((1,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(1.0, 0.0)),
-        (0, 1, Complex64::new(0.0, 0.0)),
-        (1, 0, Complex64::new(0.0, 0.0)),
-        (1, 1, Complex64::new(-1.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(0.0, 0.0)),
-        (0, 1, Complex64::new(0.0, -1.0)),
-        (1, 0, Complex64::new(0.0, 1.0)),
-        (1, 1, Complex64::new(0.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1(
-            "add_operator_exp_val",
-            ("test_off_diagonal", test_matrix, "ro"),
-        )
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
 
-    let br_type = py.get_type::<CheatedWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
+        let br_type = py.get_type::<CheatedWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
 
-    let mut measured_registers: HashMap<String, ComplexOutputRegister> = HashMap::new();
-    let _ = measured_registers.insert("ro".to_string(), register);
+        let mut measured_registers: HashMap<String, ComplexOutputRegister> = HashMap::new();
+        let _ = measured_registers.insert("ro".to_string(), register);
 
-    let input1: HashMap<String, BitOutputRegister> = HashMap::<String, BitOutputRegister>::new();
-    let input2: HashMap<String, FloatOutputRegister> =
-        HashMap::<String, FloatOutputRegister>::new();
+        let input1: HashMap<String, BitOutputRegister> =
+            HashMap::<String, BitOutputRegister>::new();
+        let input2: HashMap<String, FloatOutputRegister> =
+            HashMap::<String, FloatOutputRegister>::new();
 
-    let result = br
-        .call_method1("evaluate", (input1, input2, measured_registers))
-        .unwrap();
+        let result = br
+            .call_method1("evaluate", (input1, input2, measured_registers))
+            .unwrap();
 
-    let test_diagonal_py = f64::extract(result.get_item("test_diagonal").unwrap()).unwrap();
-    let test_off_diagonal_py = f64::extract(result.get_item("test_off_diagonal").unwrap()).unwrap();
+        let test_diagonal_py = f64::extract(result.get_item("test_diagonal").unwrap()).unwrap();
+        let test_off_diagonal_py =
+            f64::extract(result.get_item("test_off_diagonal").unwrap()).unwrap();
 
-    assert!((test_diagonal_py - value_diagonal).abs() < 1e-10);
-    assert!((test_off_diagonal_py - value_off_diagonal).abs() < 1e-10);
+        assert!((test_diagonal_py - value_diagonal).abs() < 1e-10);
+        assert!((test_off_diagonal_py - value_off_diagonal).abs() < 1e-10);
+    })
 }
 
 /// Test evaluate failure
 #[test]
 fn test_py03_evaluate_error0() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let register = vec![vec![
+            Complex64::new(1.0, 0.0),
+            Complex64::new(0.0, 0.0),
+            Complex64::new(0.0, 0.0),
+        ]];
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let register = vec![vec![
-        Complex64::new(1.0, 0.0),
-        Complex64::new(0.0, 0.0),
-        Complex64::new(0.0, 0.0),
-    ]];
-
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input = input_type
-        .call1((3,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(1.0, 0.0)),
-        (0, 1, Complex64::new(0.0, 0.0)),
-        (1, 0, Complex64::new(0.0, 0.0)),
-        (1, 1, Complex64::new(-1.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(0.0, 0.0)),
-        (0, 1, Complex64::new(0.0, -1.0)),
-        (1, 0, Complex64::new(0.0, 1.0)),
-        (1, 1, Complex64::new(0.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1(
-            "add_operator_exp_val",
-            ("test_off_diagonal", test_matrix, "ro"),
-        )
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<CheatedWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-
-    let mut measured_registers: HashMap<String, ComplexOutputRegister> = HashMap::new();
-    let _ = measured_registers.insert("ro".to_string(), register.clone());
-    let input1: HashMap<String, BitOutputRegister> = HashMap::<String, BitOutputRegister>::new();
-    let input2: HashMap<String, FloatOutputRegister> =
-        HashMap::<String, FloatOutputRegister>::new();
-
-    let result = br.call_method1(
-        "evaluate",
-        (input1, input2.clone(), measured_registers.clone()),
-    );
-    assert!(result.is_err());
-
-    let mut input1: HashMap<String, Vec<Vec<usize>>> = HashMap::new();
-    input1.insert("ro".to_string(), vec![vec![0, 0, 0]]);
-    input1.insert("ro".to_string(), vec![vec![1, 1, 1]]);
-    let error = br.call_method1("evaluate", (input1, input2, measured_registers));
-    assert!(error.is_err());
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input = input_type
+            .call1((3,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(1.0, 0.0)),
+            (0, 1, Complex64::new(0.0, 0.0)),
+            (1, 0, Complex64::new(0.0, 0.0)),
+            (1, 1, Complex64::new(-1.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(0.0, 0.0)),
+            (0, 1, Complex64::new(0.0, -1.0)),
+            (1, 0, Complex64::new(0.0, 1.0)),
+            (1, 1, Complex64::new(0.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1(
+                "add_operator_exp_val",
+                ("test_off_diagonal", test_matrix, "ro"),
+            )
+            .unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+
+        let br_type = py.get_type::<CheatedWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
+
+        let mut measured_registers: HashMap<String, ComplexOutputRegister> = HashMap::new();
+        let _ = measured_registers.insert("ro".to_string(), register.clone());
+        let input1: HashMap<String, BitOutputRegister> =
+            HashMap::<String, BitOutputRegister>::new();
+        let input2: HashMap<String, FloatOutputRegister> =
+            HashMap::<String, FloatOutputRegister>::new();
+
+        let result = br.call_method1(
+            "evaluate",
+            (input1, input2.clone(), measured_registers.clone()),
+        );
+        assert!(result.is_err());
+
+        let mut input1: HashMap<String, Vec<Vec<usize>>> = HashMap::new();
+        input1.insert("ro".to_string(), vec![vec![0, 0, 0]]);
+        input1.insert("ro".to_string(), vec![vec![1, 1, 1]]);
+        let error = br.call_method1("evaluate", (input1, input2, measured_registers));
+        assert!(error.is_err());
+    })
 }
 
 /// Test copy
 #[test]
 fn test_pyo3_copy() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input = input_type
+            .call1((3,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(1.0, 0.0)),
+            (0, 1, Complex64::new(0.0, 0.0)),
+            (1, 0, Complex64::new(0.0, 0.0)),
+            (1, 1, Complex64::new(-1.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input = input_type
-        .call1((3,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(1.0, 0.0)),
-        (0, 1, Complex64::new(0.0, 0.0)),
-        (1, 0, Complex64::new(0.0, 0.0)),
-        (1, 1, Complex64::new(-1.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
-    circs.push(circ1);
-    let br_type = py.get_type::<CheatedWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-    let br_clone = br.clone();
-
-    let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
-    let circuits_clone: Vec<CircuitWrapper> = br_clone
-        .call_method0("circuits")
-        .unwrap()
-        .extract()
-        .unwrap();
-    assert_eq!(circuits, circuits_clone);
-
-    let const_circuit: CircuitWrapper = br
-        .call_method0("constant_circuit")
-        .unwrap()
-        .extract()
-        .unwrap();
-    let const_circuit_clone: CircuitWrapper = br_clone
-        .call_method0("constant_circuit")
-        .unwrap()
-        .extract()
-        .unwrap();
-    assert_eq!(const_circuit, const_circuit_clone);
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
+        circs.push(circ1);
+        let br_type = py.get_type::<CheatedWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
+        let br_clone = br.clone();
+
+        let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
+        let circuits_clone: Vec<CircuitWrapper> = br_clone
+            .call_method0("circuits")
+            .unwrap()
+            .extract()
+            .unwrap();
+        assert_eq!(circuits, circuits_clone);
+
+        let const_circuit: CircuitWrapper = br
+            .call_method0("constant_circuit")
+            .unwrap()
+            .extract()
+            .unwrap();
+        let const_circuit_clone: CircuitWrapper = br_clone
+            .call_method0("constant_circuit")
+            .unwrap()
+            .extract()
+            .unwrap();
+        assert_eq!(const_circuit, const_circuit_clone);
+    })
 }
 
 /// Test debug and clone
 #[test]
 fn test_pyo3_debug() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input = input_type
+            .call1((3,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(1.0, 0.0)),
+            (0, 1, Complex64::new(0.0, 0.0)),
+            (1, 0, Complex64::new(0.0, 0.0)),
+            (1, 1, Complex64::new(-1.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
+            .unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+
+        let br_type = py.get_type::<CheatedWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
+        let br_wrapper = br.extract::<CheatedWrapper>().unwrap();
+
+        let br_clone = br_wrapper.clone();
+        assert_eq!(format!("{:?}", br_wrapper), format!("{:?}", br_clone));
+
+        let debug_string = "RefCell { value: CheatedWrapper { internal: Cheated { constant_circuit: Some(Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }), circuits: [Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }], input: CheatedInput { measured_operators: {\"test_diagonal\": ([(0, 0, Complex { re: 1.0, im: 0.0 }), (0, 1, Complex { re: 0.0, im: 0.0 }), (1, 0, Complex { re: 0.0, im: 0.0 }), (1, 1, Complex { re: -1.0, im: 0.0 })], \"ro\")}, number_qubits: 3 } } } }";
+        assert_eq!(format!("{:?}", br), debug_string);
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input = input_type
-        .call1((3,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(1.0, 0.0)),
-        (0, 1, Complex64::new(0.0, 0.0)),
-        (1, 0, Complex64::new(0.0, 0.0)),
-        (1, 1, Complex64::new(-1.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<CheatedWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-    let br_wrapper = br.extract::<CheatedWrapper>().unwrap();
-
-    let br_clone = br_wrapper.clone();
-    assert_eq!(format!("{:?}", br_wrapper), format!("{:?}", br_clone));
-
-    let debug_string = "RefCell { value: CheatedWrapper { internal: Cheated { constant_circuit: Some(Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }), circuits: [Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }], input: CheatedInput { measured_operators: {\"test_diagonal\": ([(0, 0, Complex { re: 1.0, im: 0.0 }), (0, 1, Complex { re: 0.0, im: 0.0 }), (1, 0, Complex { re: 0.0, im: 0.0 }), (1, 1, Complex { re: -1.0, im: 0.0 })], \"ro\")}, number_qubits: 3 } } } }";
-    assert_eq!(format!("{:?}", br), debug_string);
-
-    let debug_input_string = "RefCell { value: CheatedInputWrapper { internal: CheatedInput { measured_operators: {\"test_diagonal\": ([(0, 0, Complex { re: 1.0, im: 0.0 }), (0, 1, Complex { re: 0.0, im: 0.0 }), (1, 0, Complex { re: 0.0, im: 0.0 }), (1, 1, Complex { re: -1.0, im: 0.0 })], \"ro\")}, number_qubits: 3 } } }";
-    assert_eq!(format!("{:?}", input), debug_input_string);
-
-    let debug_input = input.clone();
-    let error = debug_input.call_method1(
-        "add_operator_exp_val",
-        (
-            "test_diagonal",
-            vec![(0, 0, Complex64::new(0.0, 0.0))],
-            "ro",
-        ),
-    );
-    assert!(error.is_err());
+        let debug_input_string = "RefCell { value: CheatedInputWrapper { internal: CheatedInput { measured_operators: {\"test_diagonal\": ([(0, 0, Complex { re: 1.0, im: 0.0 }), (0, 1, Complex { re: 0.0, im: 0.0 }), (1, 0, Complex { re: 0.0, im: 0.0 }), (1, 1, Complex { re: -1.0, im: 0.0 })], \"ro\")}, number_qubits: 3 } } }";
+        assert_eq!(format!("{:?}", input), debug_input_string);
+
+        let debug_input = input.clone();
+        let error = debug_input.call_method1(
+            "add_operator_exp_val",
+            (
+                "test_diagonal",
+                vec![(0, 0, Complex64::new(0.0, 0.0))],
+                "ro",
+            ),
+        );
+        assert!(error.is_err());
+    })
 }
 
 /// Test _internal_to_bincode function
@@ -383,143 +376,137 @@ fn test_internal_to_bincode() {
 #[test]
 fn test_to_from_json() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input = input_type
+            .call1((3,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(1.0, 0.0)),
+            (0, 1, Complex64::new(0.0, 0.0)),
+            (1, 0, Complex64::new(0.0, 0.0)),
+            (1, 1, Complex64::new(-1.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
+            .unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input = input_type
-        .call1((3,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(1.0, 0.0)),
-        (0, 1, Complex64::new(0.0, 0.0)),
-        (1, 0, Complex64::new(0.0, 0.0)),
-        (1, 1, Complex64::new(-1.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<CheatedWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-
-    let new_br = br.clone();
-    let serialised = br.call_method0("to_json").unwrap();
-    let deserialised = new_br
-        .call_method1("from_json", (serialised,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-    assert_eq!(format!("{:?}", br), format!("{:?}", deserialised));
-
-    let deserialised_error =
-        new_br.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
-    assert!(deserialised_error.is_err());
-
-    let deserialised_error =
-        new_br.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
-    assert!(deserialised_error.is_err());
-
-    let serialised_error = serialised.call_method0("to_json");
-    assert!(serialised_error.is_err());
+        let br_type = py.get_type::<CheatedWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
+
+        let new_br = br.clone();
+        let serialised = br.call_method0("to_json").unwrap();
+        let deserialised = new_br
+            .call_method1("from_json", (serialised,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
+        assert_eq!(format!("{:?}", br), format!("{:?}", deserialised));
+
+        let deserialised_error =
+            new_br.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
+        assert!(deserialised_error.is_err());
+
+        let deserialised_error =
+            new_br.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
+        assert!(deserialised_error.is_err());
+
+        let serialised_error = serialised.call_method0("to_json");
+        assert!(serialised_error.is_err());
+    })
 }
 
 /// Test substitute_parameters
 #[test]
 fn test_substitute_parameters() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input = input_type
+            .call1((3,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(1.0, 0.0)),
+            (0, 1, Complex64::new(0.0, 0.0)),
+            (1, 0, Complex64::new(0.0, 0.0)),
+            (1, 1, Complex64::new(-1.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input = input_type
-        .call1((3,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(1.0, 0.0)),
-        (0, 1, Complex64::new(0.0, 0.0)),
-        (1, 0, Complex64::new(0.0, 0.0)),
-        (1, 1, Complex64::new(-1.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
-    circs.push(circ1);
-    let br_type = py.get_type::<CheatedWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-
-    let mut map: HashMap<String, f64> = HashMap::<String, f64>::new();
-    map.insert("theta".to_string(), 0.0);
-    let br_sub = br
-        .call_method1("substitute_parameters", (map,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-
-    let br_wrapper = br.extract::<CheatedWrapper>().unwrap();
-    let br_sub_wrapper = br_sub.extract::<CheatedWrapper>().unwrap();
-    assert_ne!(format!("{:?}", br_wrapper), format!("{:?}", br_sub_wrapper));
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
+        circs.push(circ1);
+        let br_type = py.get_type::<CheatedWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
+
+        let mut map: HashMap<String, f64> = HashMap::<String, f64>::new();
+        map.insert("theta".to_string(), 0.0);
+        let br_sub = br
+            .call_method1("substitute_parameters", (map,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
+
+        let br_wrapper = br.extract::<CheatedWrapper>().unwrap();
+        let br_sub_wrapper = br_sub.extract::<CheatedWrapper>().unwrap();
+        assert_ne!(format!("{:?}", br_wrapper), format!("{:?}", br_sub_wrapper));
+    })
 }
 
 /// Test substitute_parameters returning an error
 #[test]
 fn test_substitute_parameters_error() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input = input_type
+            .call1((3,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
+        let test_matrix = vec![
+            (0, 0, Complex64::new(1.0, 0.0)),
+            (0, 1, Complex64::new(0.0, 0.0)),
+            (1, 0, Complex64::new(0.0, 0.0)),
+            (1, 1, Complex64::new(-1.0, 0.0)),
+        ];
+        let _ = input
+            .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
+            .unwrap();
+
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
+        circs.push(circ1);
+        let br_type = py.get_type::<CheatedWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input = input_type
-        .call1((3,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
-    let test_matrix = vec![
-        (0, 0, Complex64::new(1.0, 0.0)),
-        (0, 1, Complex64::new(0.0, 0.0)),
-        (1, 0, Complex64::new(0.0, 0.0)),
-        (1, 1, Complex64::new(-1.0, 0.0)),
-    ];
-    let _ = input
-        .call_method1("add_operator_exp_val", ("test_diagonal", test_matrix, "ro"))
-        .unwrap();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
-    circs.push(circ1);
-    let br_type = py.get_type::<CheatedWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
-
-    let map: HashMap<String, f64> = HashMap::<String, f64>::new();
-    let br_sub = br.call_method1("substitute_parameters", (map,));
-    assert!(br_sub.is_err());
+        let map: HashMap<String, f64> = HashMap::<String, f64>::new();
+        let br_sub = br.call_method1("substitute_parameters", (map,));
+        assert!(br_sub.is_err());
+    })
 }
diff --git a/qoqo/tests/integration/measurements/classical_register_measurement.rs b/qoqo/tests/integration/measurements/classical_register_measurement.rs
index 0562932d..8d53b708 100644
--- a/qoqo/tests/integration/measurements/classical_register_measurement.rs
+++ b/qoqo/tests/integration/measurements/classical_register_measurement.rs
@@ -23,100 +23,94 @@ use std::collections::HashMap;
 #[test]
 fn test_returning_circuits() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
+        circs.push(circ1);
+        let br_type = py.get_type::<ClassicalRegisterWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone()))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
-    circs.push(circ1);
-    let br_type = py.get_type::<ClassicalRegisterWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone()))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
-
-    let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
-    for (index, b) in circuits.iter().enumerate() {
-        assert_eq!(b, circs.get(index).unwrap());
-    }
-    let const_circuit: CircuitWrapper = br
-        .call_method0("constant_circuit")
-        .unwrap()
-        .extract()
-        .unwrap();
-    assert_eq!(CircuitWrapper::new(), const_circuit);
+        let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
+        for (index, b) in circuits.iter().enumerate() {
+            assert_eq!(b, circs.get(index).unwrap());
+        }
+        let const_circuit: CircuitWrapper = br
+            .call_method0("constant_circuit")
+            .unwrap()
+            .extract()
+            .unwrap();
+        assert_eq!(CircuitWrapper::new(), const_circuit);
+    })
 }
 
 /// Test copy
 #[test]
 fn test_pyo3_copy() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
+        circs.push(circ1);
+        let br_type = py.get_type::<ClassicalRegisterWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone()))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
+        let br_clone = br.clone();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, 0.0.into());
-    circs.push(circ1);
-    let br_type = py.get_type::<ClassicalRegisterWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone()))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
-    let br_clone = br.clone();
-
-    let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
-    let circuits_clone: Vec<CircuitWrapper> = br_clone
-        .call_method0("circuits")
-        .unwrap()
-        .extract()
-        .unwrap();
-    assert_eq!(circuits, circuits_clone);
-
-    let const_circuit: CircuitWrapper = br
-        .call_method0("constant_circuit")
-        .unwrap()
-        .extract()
-        .unwrap();
-    let const_circuit_clone: CircuitWrapper = br_clone
-        .call_method0("constant_circuit")
-        .unwrap()
-        .extract()
-        .unwrap();
-    assert_eq!(const_circuit, const_circuit_clone);
+        let circuits: Vec<CircuitWrapper> = br.call_method0("circuits").unwrap().extract().unwrap();
+        let circuits_clone: Vec<CircuitWrapper> = br_clone
+            .call_method0("circuits")
+            .unwrap()
+            .extract()
+            .unwrap();
+        assert_eq!(circuits, circuits_clone);
+
+        let const_circuit: CircuitWrapper = br
+            .call_method0("constant_circuit")
+            .unwrap()
+            .extract()
+            .unwrap();
+        let const_circuit_clone: CircuitWrapper = br_clone
+            .call_method0("constant_circuit")
+            .unwrap()
+            .extract()
+            .unwrap();
+        assert_eq!(const_circuit, const_circuit_clone);
+    })
 }
 
 /// Test debug and clone
 #[test]
 fn test_pyo3_debug() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<ClassicalRegisterWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone()))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
-    let br_wrapper = br.extract::<ClassicalRegisterWrapper>().unwrap();
+        let br_type = py.get_type::<ClassicalRegisterWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone()))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
+        let br_wrapper = br.extract::<ClassicalRegisterWrapper>().unwrap();
 
-    let br_clone = br_wrapper.clone();
-    assert_eq!(format!("{:?}", br_wrapper), format!("{:?}", br_clone));
+        let br_clone = br_wrapper.clone();
+        assert_eq!(format!("{:?}", br_wrapper), format!("{:?}", br_clone));
 
-    let debug_string = "RefCell { value: ClassicalRegisterWrapper { internal: ClassicalRegister { constant_circuit: Some(Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }), circuits: [Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }] } } }";
-    assert_eq!(format!("{:?}", br), debug_string);
+        let debug_string = "RefCell { value: ClassicalRegisterWrapper { internal: ClassicalRegister { constant_circuit: Some(Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }), circuits: [Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion }] } } }";
+        assert_eq!(format!("{:?}", br), debug_string);
+    })
 }
 
 /// Test _internal_to_bincode function
@@ -156,93 +150,88 @@ fn test_internal_to_bincode() {
 #[test]
 fn test_to_from_json() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+
+        let br_type = py.get_type::<ClassicalRegisterWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone()))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-
-    let br_type = py.get_type::<ClassicalRegisterWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone()))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
-
-    let new_br = br.clone();
-    let serialised = br.call_method0("to_json").unwrap();
-    let deserialised = new_br
-        .call_method1("from_json", (serialised,))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
-    assert_eq!(format!("{:?}", br), format!("{:?}", deserialised));
-
-    let deserialised_error =
-        new_br.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
-    assert!(deserialised_error.is_err());
-
-    let deserialised_error =
-        new_br.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
-    assert!(deserialised_error.is_err());
-
-    let serialised_error = serialised.call_method0("to_json");
-    assert!(serialised_error.is_err());
+        let new_br = br.clone();
+        let serialised = br.call_method0("to_json").unwrap();
+        let deserialised = new_br
+            .call_method1("from_json", (serialised,))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
+        assert_eq!(format!("{:?}", br), format!("{:?}", deserialised));
+
+        let deserialised_error =
+            new_br.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
+        assert!(deserialised_error.is_err());
+
+        let deserialised_error =
+            new_br.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
+        assert!(deserialised_error.is_err());
+
+        let serialised_error = serialised.call_method0("to_json");
+        assert!(serialised_error.is_err());
+    })
 }
 
 /// Test substitute_parameters
 #[test]
 fn test_substitute_parameters() {
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
-    circs.push(circ1);
-    let br_type = py.get_type::<ClassicalRegisterWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone()))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
-
-    let mut map: HashMap<String, f64> = HashMap::<String, f64>::new();
-    map.insert("theta".to_string(), 0.0);
-    let br_sub = br
-        .call_method1("substitute_parameters", (map,))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
-
-    let br_wrapper = br.extract::<ClassicalRegisterWrapper>().unwrap();
-    let br_sub_wrapper = br_sub.extract::<ClassicalRegisterWrapper>().unwrap();
-    assert_ne!(format!("{:?}", br_wrapper), format!("{:?}", br_sub_wrapper));
+    Python::with_gil(|py| -> () {
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
+        circs.push(circ1);
+        let br_type = py.get_type::<ClassicalRegisterWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone()))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
+
+        let mut map: HashMap<String, f64> = HashMap::<String, f64>::new();
+        map.insert("theta".to_string(), 0.0);
+        let br_sub = br
+            .call_method1("substitute_parameters", (map,))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
+
+        let br_wrapper = br.extract::<ClassicalRegisterWrapper>().unwrap();
+        let br_sub_wrapper = br_sub.extract::<ClassicalRegisterWrapper>().unwrap();
+        assert_ne!(format!("{:?}", br_wrapper), format!("{:?}", br_sub_wrapper));
+    })
 }
 
 /// Test substitute_parameters returning an error
 #[test]
 fn test_substitute_parameters_error() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
+        circs.push(circ1);
+        let br_type = py.get_type::<ClassicalRegisterWrapper>();
+        let br = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone()))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
 
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += roqoqo::operations::RotateX::new(0, "theta".into());
-    circs.push(circ1);
-    let br_type = py.get_type::<ClassicalRegisterWrapper>();
-    let br = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone()))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
-
-    let map: HashMap<String, f64> = HashMap::<String, f64>::new();
-    let br_sub = br.call_method1("substitute_parameters", (map,));
-    assert!(br_sub.is_err());
+        let map: HashMap<String, f64> = HashMap::<String, f64>::new();
+        let br_sub = br.call_method1("substitute_parameters", (map,));
+        assert!(br_sub.is_err());
+    })
 }
diff --git a/qoqo/tests/integration/operations/define_operations.rs b/qoqo/tests/integration/operations/define_operations.rs
index c62c4949..4228d961 100644
--- a/qoqo/tests/integration/operations/define_operations.rs
+++ b/qoqo/tests/integration/operations/define_operations.rs
@@ -20,220 +20,216 @@ use test_case::test_case;
 #[test]
 fn test_pyo3_new_definition_float() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<DefinitionFloatWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), 1, false))
+            .unwrap()
+            .cast_as::<PyCell<DefinitionFloatWrapper>>()
+            .unwrap();
 
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<DefinitionFloatWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), 1, false))
-        .unwrap()
-        .cast_as::<PyCell<DefinitionFloatWrapper>>()
+        let input_definition = Operation::from(DefinitionFloat::new(String::from("ro"), 1, false));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison_copy);
 
-    let input_definition = Operation::from(DefinitionFloat::new(String::from("ro"), 1, false));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let def_wrapper = new_op.extract::<DefinitionFloatWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("ro".to_string(), 1, true))
-        .unwrap()
-        .cast_as::<PyCell<DefinitionFloatWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<DefinitionFloatWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper),
-        "DefinitionFloatWrapper { internal: DefinitionFloat { name: \"ro\", length: 1, is_output: false } }"
-    );
+        let def_wrapper = new_op.extract::<DefinitionFloatWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("ro".to_string(), 1, true))
+            .unwrap()
+            .cast_as::<PyCell<DefinitionFloatWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<DefinitionFloatWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper),
+            "DefinitionFloatWrapper { internal: DefinitionFloat { name: \"ro\", length: 1, is_output: false } }"
+        );
+    })
 }
 
 /// Test DefinitionComplex new() function
 #[test]
 fn test_pyo3_new_definition_complex() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<DefinitionComplexWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), 1, false))
+            .unwrap()
+            .cast_as::<PyCell<DefinitionComplexWrapper>>()
+            .unwrap();
 
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<DefinitionComplexWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), 1, false))
-        .unwrap()
-        .cast_as::<PyCell<DefinitionComplexWrapper>>()
+        let input_definition =
+            Operation::from(DefinitionComplex::new(String::from("ro"), 1, false));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison_copy);
 
-    let input_definition = Operation::from(DefinitionComplex::new(String::from("ro"), 1, false));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let def_wrapper = new_op.extract::<DefinitionComplexWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("ro".to_string(), 1, true))
-        .unwrap()
-        .cast_as::<PyCell<DefinitionComplexWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<DefinitionComplexWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper),
-        "DefinitionComplexWrapper { internal: DefinitionComplex { name: \"ro\", length: 1, is_output: false } }"
-    );
+        let def_wrapper = new_op.extract::<DefinitionComplexWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("ro".to_string(), 1, true))
+            .unwrap()
+            .cast_as::<PyCell<DefinitionComplexWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<DefinitionComplexWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper),
+            "DefinitionComplexWrapper { internal: DefinitionComplex { name: \"ro\", length: 1, is_output: false } }"
+        );
+    })
 }
 
 /// Test DefinitionUsize new() function
 #[test]
 fn test_pyo3_new_definition_usize() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<DefinitionUsizeWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), 1, false))
+            .unwrap()
+            .cast_as::<PyCell<DefinitionUsizeWrapper>>()
+            .unwrap();
 
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<DefinitionUsizeWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), 1, false))
-        .unwrap()
-        .cast_as::<PyCell<DefinitionUsizeWrapper>>()
+        let input_definition = Operation::from(DefinitionUsize::new(String::from("ro"), 1, false));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison_copy);
 
-    let input_definition = Operation::from(DefinitionUsize::new(String::from("ro"), 1, false));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let def_wrapper = new_op.extract::<DefinitionUsizeWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("ro".to_string(), 1, true))
-        .unwrap()
-        .cast_as::<PyCell<DefinitionUsizeWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<DefinitionUsizeWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper),
-        "DefinitionUsizeWrapper { internal: DefinitionUsize { name: \"ro\", length: 1, is_output: false } }"
-    );
+        let def_wrapper = new_op.extract::<DefinitionUsizeWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("ro".to_string(), 1, true))
+            .unwrap()
+            .cast_as::<PyCell<DefinitionUsizeWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<DefinitionUsizeWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper),
+            "DefinitionUsizeWrapper { internal: DefinitionUsize { name: \"ro\", length: 1, is_output: false } }"
+        );
+    })
 }
 
 /// Test DefinitionBit new() function
 #[test]
 fn test_pyo3_new_definition_bit() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<DefinitionBitWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), 1, false))
+            .unwrap()
+            .cast_as::<PyCell<DefinitionBitWrapper>>()
+            .unwrap();
 
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<DefinitionBitWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), 1, false))
-        .unwrap()
-        .cast_as::<PyCell<DefinitionBitWrapper>>()
+        let input_definition = Operation::from(DefinitionBit::new(String::from("ro"), 1, false));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison_copy);
 
-    let input_definition = Operation::from(DefinitionBit::new(String::from("ro"), 1, false));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let def_wrapper = new_op.extract::<DefinitionBitWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("ro".to_string(), 1, true))
-        .unwrap()
-        .cast_as::<PyCell<DefinitionBitWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<DefinitionBitWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper),
-        "DefinitionBitWrapper { internal: DefinitionBit { name: \"ro\", length: 1, is_output: false } }"
-    );
+        let def_wrapper = new_op.extract::<DefinitionBitWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("ro".to_string(), 1, true))
+            .unwrap()
+            .cast_as::<PyCell<DefinitionBitWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<DefinitionBitWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper),
+            "DefinitionBitWrapper { internal: DefinitionBit { name: \"ro\", length: 1, is_output: false } }"
+        );
+    })
 }
 
 /// Test InputSymbolic new() function
 #[test]
 fn test_pyo3_new_input_symbolic() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<InputSymbolicWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), 1.0))
+            .unwrap()
+            .cast_as::<PyCell<InputSymbolicWrapper>>()
+            .unwrap();
 
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<InputSymbolicWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), 1.0))
-        .unwrap()
-        .cast_as::<PyCell<InputSymbolicWrapper>>()
+        let input_definition = Operation::from(InputSymbolic::new(String::from("ro"), 1.0));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison_copy);
 
-    let input_definition = Operation::from(InputSymbolic::new(String::from("ro"), 1.0));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let def_wrapper = new_op.extract::<InputSymbolicWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("ro".to_string(), 2.0))
-        .unwrap()
-        .cast_as::<PyCell<InputSymbolicWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<InputSymbolicWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper),
-        "InputSymbolicWrapper { internal: InputSymbolic { name: \"ro\", input: 1.0 } }"
-    );
+        let def_wrapper = new_op.extract::<InputSymbolicWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("ro".to_string(), 2.0))
+            .unwrap()
+            .cast_as::<PyCell<InputSymbolicWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<InputSymbolicWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper),
+            "InputSymbolicWrapper { internal: InputSymbolic { name: \"ro\", input: 1.0 } }"
+        );
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit, InputSymbolic name() function/input
@@ -244,14 +240,13 @@ fn test_pyo3_new_input_symbolic() {
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)); "InputSymbolic")]
 fn test_pyo3_name(input_definition: Operation) {
     pyo3::prepare_freethreaded_python();
-
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let name_op: String =
-        String::extract(operation.call_method0(py, "name").unwrap().as_ref(py)).unwrap();
-    let name_param: String = String::from("ro");
-    assert_eq!(name_op, name_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let name_op: String =
+            String::extract(operation.call_method0(py, "name").unwrap().as_ref(py)).unwrap();
+        let name_param: String = String::from("ro");
+        assert_eq!(name_op, name_param);
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit length() input
@@ -260,13 +255,13 @@ fn test_pyo3_name(input_definition: Operation) {
 #[test_case(Operation::from(DefinitionUsize::new(String::from("ro"), 1, false)); "DefinitionUsize")]
 #[test_case(Operation::from(DefinitionBit::new(String::from("ro"), 1, false)); "DefinitionBit")]
 fn test_pyo3_length(input_definition: Operation) {
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let length_op: &usize =
-        &usize::extract(operation.call_method0(py, "length").unwrap().as_ref(py)).unwrap();
-    let length_param: &usize = &1_usize;
-    assert_eq!(length_op, length_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let length_op: &usize =
+            &usize::extract(operation.call_method0(py, "length").unwrap().as_ref(py)).unwrap();
+        let length_param: &usize = &1_usize;
+        assert_eq!(length_op, length_param);
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit is_output() input
@@ -275,26 +270,29 @@ fn test_pyo3_length(input_definition: Operation) {
 #[test_case(Operation::from(DefinitionUsize::new(String::from("ro"), 1, false)); "DefinitionUsize")]
 #[test_case(Operation::from(DefinitionBit::new(String::from("ro"), 1, false)); "DefinitionBit")]
 fn test_pyo3_is_output(input_definition: Operation) {
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    assert!(!bool::extract(operation.call_method0(py, "is_output").unwrap().as_ref(py)).unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        assert!(
+            !bool::extract(operation.call_method0(py, "is_output").unwrap().as_ref(py)).unwrap()
+        );
+    })
 }
 
 /// Test InputSymbolic input() input
 #[test]
 fn test_pyo3_input_symbolic_input() {
     pyo3::prepare_freethreaded_python();
-
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation =
-        convert_operation_to_pyobject(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)))
-            .unwrap();
-    let input_op: &f64 =
-        &f64::extract(operation.call_method0(py, "input").unwrap().as_ref(py)).unwrap();
-    let input_param: &f64 = &1.0;
-    assert_eq!(input_op, input_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(Operation::from(InputSymbolic::new(
+            String::from("ro"),
+            1.0,
+        )))
+        .unwrap();
+        let input_op: &f64 =
+            &f64::extract(operation.call_method0(py, "input").unwrap().as_ref(py)).unwrap();
+        let input_param: &f64 = &1.0;
+        assert_eq!(input_op, input_param);
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit, InputSymbolic involved_qubits function
@@ -304,18 +302,18 @@ fn test_pyo3_input_symbolic_input() {
 #[test_case(Operation::from(DefinitionBit::new(String::from("ro"), 1, false)); "DefinitionBit")]
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)); "InputSymbolic")]
 fn test_pyo3_involved_qubits(input_definition: Operation) {
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let involved_op: HashSet<String> = HashSet::extract(
-        operation
-            .call_method0(py, "involved_qubits")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    let involved_param: HashSet<_> = HashSet::new();
-    assert_eq!(involved_op, involved_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let involved_op: HashSet<String> = HashSet::extract(
+            operation
+                .call_method0(py, "involved_qubits")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        let involved_param: HashSet<_> = HashSet::new();
+        assert_eq!(involved_op, involved_param);
+    })
 }
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit format and repr functions
 #[test_case(Operation::from(DefinitionFloat::new(String::from("ro"), 1, false)), "DefinitionFloat"; "DefinitionFloat")]
@@ -324,37 +322,38 @@ fn test_pyo3_involved_qubits(input_definition: Operation) {
 #[test_case(Operation::from(DefinitionBit::new(String::from("ro"), 1, false)), "DefinitionBit"; "DefinitionBit")]
 fn test_pyo3_format_repr(input_definition: Operation, format_repr: &str) {
     pyo3::prepare_freethreaded_python();
-
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-    let to_repr = operation.call_method0(py, "__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-    let mut format_repr_param: String = String::from(format_repr);
-    format_repr_param.push_str(" { name: \"ro\", length: 1, is_output: false }");
-    let comparison = format_repr_param.as_str();
-    assert_eq!(format_op, comparison);
-    assert_eq!(repr_op, comparison);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+        let to_repr = operation.call_method0(py, "__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+        let mut format_repr_param: String = String::from(format_repr);
+        format_repr_param.push_str(" { name: \"ro\", length: 1, is_output: false }");
+        let comparison = format_repr_param.as_str();
+        assert_eq!(format_op, comparison);
+        assert_eq!(repr_op, comparison);
+    })
 }
 
 /// Test InputSymbolic format and repr functions
 #[test]
 fn test_pyo3_input_symbolic_format_repr() {
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation =
-        convert_operation_to_pyobject(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)))
-            .unwrap();
-    let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-    let to_repr = operation.call_method0(py, "__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-    let format_repr_param: String = String::from("InputSymbolic { name: \"ro\", input: 1.0 }");
-    let comparison = format_repr_param.as_str();
-    assert_eq!(format_op, comparison);
-    assert_eq!(repr_op, comparison);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(Operation::from(InputSymbolic::new(
+            String::from("ro"),
+            1.0,
+        )))
+        .unwrap();
+        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+        let to_repr = operation.call_method0(py, "__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+        let format_repr_param: String = String::from("InputSymbolic { name: \"ro\", input: 1.0 }");
+        let comparison = format_repr_param.as_str();
+        assert_eq!(format_op, comparison);
+        assert_eq!(repr_op, comparison);
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit, InputSymbolic copy and deepcopy functions
@@ -364,29 +363,29 @@ fn test_pyo3_input_symbolic_format_repr() {
 #[test_case(Operation::from(DefinitionBit::new(String::from("ro"), 1, false)); "DefinitionBit")]
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)); "InputSymbolic")]
 fn test_pyo3_copy_deepcopy(input_definition: Operation) {
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let copy_op = operation.call_method0(py, "__copy__").unwrap();
-    let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
-    let copy_deepcopy_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        copy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-    let comparison_deepcopy = bool::extract(
-        deepcopy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let copy_op = operation.call_method0(py, "__copy__").unwrap();
+        let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
+        let copy_deepcopy_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            copy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+        let comparison_deepcopy = bool::extract(
+            deepcopy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit, InputSymbolic tags function
@@ -397,14 +396,13 @@ fn test_pyo3_copy_deepcopy(input_definition: Operation) {
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)), "InputSymbolic"; "InputSymbolic")]
 fn test_pyo3_tags(input_definition: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &["Operation", "Definition", tag_name];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &["Operation", "Definition", tag_name];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit, InputSymbolic hqslang function
@@ -415,13 +413,12 @@ fn test_pyo3_tags(input_definition: Operation, tag_name: &str) {
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)), String::from("InputSymbolic"); "InputSymbolic")]
 fn test_pyo3_hqslang(input_definition: Operation, hqslang_param: String) {
     pyo3::prepare_freethreaded_python();
-
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let hqslang_op: String =
-        String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
-    assert_eq!(hqslang_op, hqslang_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let hqslang_op: String =
+            String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
+        assert_eq!(hqslang_op, hqslang_param);
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit, InputSymbolic is_parametrized function
@@ -431,16 +428,16 @@ fn test_pyo3_hqslang(input_definition: Operation, hqslang_param: String) {
 #[test_case(Operation::from(DefinitionBit::new(String::from("ro"), 1, false)); "DefinitionBit")]
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)); "InputSymbolic")]
 fn test_pyo3_is_parametrized(input_definition: Operation) {
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    assert!(!bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        assert!(!bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit substitute_parameters functions
@@ -450,24 +447,24 @@ fn test_pyo3_is_parametrized(input_definition: Operation) {
 #[test_case(Operation::from(DefinitionBit::new(String::from("ro"), 1, false)); "DefinitionBit")]
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)); "InputSymbolic")]
 fn test_pyo3_substitute_parameters(input_definition: Operation) {
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
-    substitution_dict.insert("ro", 1.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict,))
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
+        substitution_dict.insert("ro", 1.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict,))
+            .unwrap();
+        let substitute_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (substitute_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let substitute_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (substitute_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
+        assert!(comparison_copy);
+    })
 }
 
 /// Test substitute_parameters() causing an error `not-a-real-number`
@@ -478,16 +475,16 @@ fn test_pyo3_substitute_parameters(input_definition: Operation) {
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)); "InputSymbolic")]
 fn test_pyo3_substitute_parameters_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let mut substitution_dict: HashMap<&str, &str> = HashMap::new();
-    substitution_dict.insert("ro", "test");
-    let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let mut substitution_dict: HashMap<&str, &str> = HashMap::new();
+        substitution_dict.insert("ro", "test");
+        let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
+
 /// Test DefinitionFloat, DefinitionComplex, DefinitionUsize, DefinitionBit remap_qubits functions
 #[test_case(Operation::from(DefinitionFloat::new(String::from("ro"), 1, false)); "DefinitionFloat")]
 #[test_case(Operation::from(DefinitionComplex::new(String::from("ro"), 1, false)); "DefinitionComplex")]
@@ -496,25 +493,24 @@ fn test_pyo3_substitute_parameters_error(input_operation: Operation) {
 #[test_case(Operation::from(InputSymbolic::new(String::from("ro"), 1.0)); "InputSymbolic")]
 fn test_pyo3_remap_qubits(input_definition: Operation) {
     pyo3::prepare_freethreaded_python();
-
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    qubit_mapping.insert(0, 1);
-    let remap_op = operation
-        .call_method1(py, "remap_qubits", (qubit_mapping,))
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        qubit_mapping.insert(0, 1);
+        let remap_op = operation
+            .call_method1(py, "remap_qubits", (qubit_mapping,))
+            .unwrap();
+        let remap_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            remap_op
+                .as_ref(py)
+                .call_method1("__eq__", (remap_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let remap_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        remap_op
-            .as_ref(py)
-            .call_method1("__eq__", (remap_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
+        assert!(comparison_copy);
+    })
 }
 
 /// Test the __richcmp__ function
@@ -535,33 +531,32 @@ fn test_pyo3_remap_qubits(input_definition: Operation) {
             "InputSymbolic")]
 fn test_pyo3_richcmp(definition_1: Operation, definition_2: Operation) {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
+        let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__eq__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(!comparison);
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__ne__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+
+        let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
+        assert!(comparison.is_err());
 
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
-    let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__eq__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(!comparison);
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__ne__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
-    assert!(comparison.is_err());
-
-    let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
+        assert!(comparison.is_err());
+    })
 }
diff --git a/qoqo/tests/integration/operations/measurement_operations.rs b/qoqo/tests/integration/operations/measurement_operations.rs
index e25097d2..49da253b 100644
--- a/qoqo/tests/integration/operations/measurement_operations.rs
+++ b/qoqo/tests/integration/operations/measurement_operations.rs
@@ -66,15 +66,13 @@ fn new_circuit(py: Python) -> &PyCell<CircuitWrapper> {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))); "PragmaRepeatedMeasurement")]
 fn test_pyo3_readout(input_measurement: Operation) {
     pyo3::prepare_freethreaded_python();
-
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let readout_op: &String =
-        &String::extract(operation.call_method0(py, "readout").unwrap().as_ref(py)).unwrap();
-    let readout_param: String = String::from("ro");
-    assert_eq!(readout_op, &readout_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let readout_op: &String =
+            &String::extract(operation.call_method0(py, "readout").unwrap().as_ref(py)).unwrap();
+        let readout_param: String = String::from("ro");
+        assert_eq!(readout_op, &readout_param);
+    })
 }
 
 /// Test qubit_mapping() or qubit_paulis input/function
@@ -82,19 +80,17 @@ fn test_pyo3_readout(input_measurement: Operation) {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))), "qubit_mapping"; "PragmaRepeatedMeasurement")]
 fn test_pyo3_qubit_mapping(input_measurement: Operation, operation_name: &str) {
     pyo3::prepare_freethreaded_python();
-
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let readout_op: &HashMap<usize, usize> = &HashMap::extract(
-        operation
-            .call_method0(py, operation_name)
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(readout_op, &create_qubit_mapping());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let readout_op: &HashMap<usize, usize> = &HashMap::extract(
+            operation
+                .call_method0(py, operation_name)
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(readout_op, &create_qubit_mapping());
+    })
 }
 
 /// Test circuit() input/function
@@ -104,73 +100,70 @@ fn test_pyo3_qubit_mapping(input_measurement: Operation, operation_name: &str) {
 #[test_case(Operation::from(PragmaGetPauliProduct::new(create_qubit_mapping(), String::from("ro"), create_circuit())); "PragmaGetPauliProduct")]
 fn test_pyo3_circuit(input_measurement: Operation) {
     pyo3::prepare_freethreaded_python();
-
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_circuit = operation.call_method0(py, "circuit").unwrap();
-    let circuit_op = to_circuit.as_ref(py);
-
-    let circuit = new_circuit(py);
-    let paulix = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
-    circuit.call_method1("add", (paulix.clone(),)).unwrap();
-
-    let comparison_circuit =
-        bool::extract(circuit_op.call_method1("__eq__", (circuit,)).unwrap()).unwrap();
-    assert!(comparison_circuit);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_circuit = operation.call_method0(py, "circuit").unwrap();
+        let circuit_op = to_circuit.as_ref(py);
+
+        let circuit = new_circuit(py);
+        let paulix = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
+        circuit.call_method1("add", (paulix.clone(),)).unwrap();
+
+        let comparison_circuit =
+            bool::extract(circuit_op.call_method1("__eq__", (circuit,)).unwrap()).unwrap();
+        assert!(comparison_circuit);
+    })
 }
 
 /// Test MeasureQubit remaining inputs (qubit, readout_index)
 #[test]
 fn test_pyo3_input_measurequbit_input() {
     pyo3::prepare_freethreaded_python();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(Operation::from(MeasureQubit::new(
+            0,
+            String::from("ro"),
+            1,
+        )))
+        .unwrap();
 
-    pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation =
-        convert_operation_to_pyobject(Operation::from(MeasureQubit::new(0, String::from("ro"), 1)))
-            .unwrap();
-
-    let qubit_op: &usize =
-        &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
-    let qubit_param: &usize = &0;
-    assert_eq!(qubit_op, qubit_param);
-
-    let ro_index_op: &usize = &usize::extract(
-        operation
-            .call_method0(py, "readout_index")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    let ro_index_param: &usize = &1;
-    assert_eq!(ro_index_op, ro_index_param);
+        let qubit_op: &usize =
+            &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
+        let qubit_param: &usize = &0;
+        assert_eq!(qubit_op, qubit_param);
+
+        let ro_index_op: &usize = &usize::extract(
+            operation
+                .call_method0(py, "readout_index")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        let ro_index_param: &usize = &1;
+        assert_eq!(ro_index_op, ro_index_param);
+    })
 }
 
 /// Test PragmaRepeatedMeasurement remaining input (number_mreasurements)
 #[test]
 fn test_pyo3_input_pragmarepeatedmeasurements_input() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(Operation::from(PragmaRepeatedMeasurement::new(
-        String::from("ro"),
-        2,
-        Some(create_qubit_mapping()),
-    )))
-    .unwrap();
-
-    let nbr_meas_op: &usize = &usize::extract(
-        operation
-            .call_method0(py, "number_measurements")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    let nbr_meas_param: &usize = &2;
-    assert_eq!(nbr_meas_op, nbr_meas_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(Operation::from(
+            PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping())),
+        ))
+        .unwrap();
+
+        let nbr_meas_op: &usize = &usize::extract(
+            operation
+                .call_method0(py, "number_measurements")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        let nbr_meas_param: &usize = &2;
+        assert_eq!(nbr_meas_op, nbr_meas_param);
+    })
 }
 
 /// Test involved_qubits function for Pragmas with All
@@ -180,14 +173,14 @@ fn test_pyo3_input_pragmarepeatedmeasurements_input() {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))); "PragmaRepeatedMeasurement")]
 fn test_pyo3_involved_qubits_all(input_definition: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
-    let involved_op: HashSet<&str> = HashSet::extract(to_involved.as_ref(py)).unwrap();
-    let mut involved_param: HashSet<&str> = HashSet::new();
-    involved_param.insert("All");
-    assert_eq!(involved_op, involved_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
+        let involved_op: HashSet<&str> = HashSet::extract(to_involved.as_ref(py)).unwrap();
+        let mut involved_param: HashSet<&str> = HashSet::new();
+        involved_param.insert("All");
+        assert_eq!(involved_op, involved_param);
+    })
 }
 
 /// Test involved_qubits function for pragmas with qubit 0
@@ -195,14 +188,14 @@ fn test_pyo3_involved_qubits_all(input_definition: Operation) {
 #[test_case(Operation::from(PragmaGetPauliProduct::new(create_qubit_mapping(), String::from("ro"), create_circuit())); "PragmaGetPauliProduct")]
 fn test_pyo3_involved_qubits_0(input_definition: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
-    let involved_op: HashSet<usize> = HashSet::extract(to_involved.as_ref(py)).unwrap();
-    let mut involved_param: HashSet<usize> = HashSet::new();
-    involved_param.insert(0);
-    assert_eq!(involved_op, involved_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
+        let involved_op: HashSet<usize> = HashSet::extract(to_involved.as_ref(py)).unwrap();
+        let mut involved_param: HashSet<usize> = HashSet::new();
+        involved_param.insert(0);
+        assert_eq!(involved_op, involved_param);
+    })
 }
 
 /// Test format and repr functions
@@ -214,15 +207,15 @@ fn test_pyo3_involved_qubits_0(input_definition: Operation) {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))), "PragmaRepeatedMeasurement { readout: \"ro\", number_measurements: 2, qubit_mapping: Some({0: 1}) }"; "PragmaRepeatedMeasurement")]
 fn test_pyo3_format_repr(input_measurement: Operation, format_repr: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-    let to_repr = operation.call_method0(py, "__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-    assert_eq!(format_op, format_repr);
-    assert_eq!(repr_op, format_repr);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+        let to_repr = operation.call_method0(py, "__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+        assert_eq!(format_op, format_repr);
+        assert_eq!(repr_op, format_repr);
+    })
 }
 
 /// Test copy and deepcopy functions
@@ -234,29 +227,29 @@ fn test_pyo3_format_repr(input_measurement: Operation, format_repr: &str) {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))); "PragmaRepeatedMeasurement")]
 fn test_pyo3_copy_deepcopy(input_measurement: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let copy_op = operation.call_method0(py, "__copy__").unwrap();
-    let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
-    let copy_deepcopy_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        copy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-    let comparison_deepcopy = bool::extract(
-        deepcopy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let copy_op = operation.call_method0(py, "__copy__").unwrap();
+        let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
+        let copy_deepcopy_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            copy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+        let comparison_deepcopy = bool::extract(
+            deepcopy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 /// Test tags function
@@ -267,28 +260,31 @@ fn test_pyo3_copy_deepcopy(input_measurement: Operation) {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))), "PragmaRepeatedMeasurement"; "PragmaRepeatedMeasurement")]
 fn test_pyo3_tags(input_measurement: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &["Operation", "Measurement", "PragmaOperation", tag_name];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &["Operation", "Measurement", "PragmaOperation", tag_name];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test tags function for MeasureQubit
 #[test]
 fn test_pyo3_tags() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation =
-        convert_operation_to_pyobject(Operation::from(MeasureQubit::new(0, String::from("ro"), 0)))
-            .unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &["Operation", "Measurement", "MeasureQubit"];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(Operation::from(MeasureQubit::new(
+            0,
+            String::from("ro"),
+            0,
+        )))
+        .unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &["Operation", "Measurement", "MeasureQubit"];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test hqslang function
@@ -300,12 +296,12 @@ fn test_pyo3_tags() {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))), String::from("PragmaRepeatedMeasurement"); "PragmaRepeatedMeasurement")]
 fn test_pyo3_hqslang(input_measurement: Operation, hqslang_param: String) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let hqslang_op: String =
-        String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
-    assert_eq!(hqslang_op, hqslang_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let hqslang_op: String =
+            String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
+        assert_eq!(hqslang_op, hqslang_param);
+    })
 }
 
 /// Test is_parametrized function
@@ -317,16 +313,16 @@ fn test_pyo3_hqslang(input_measurement: Operation, hqslang_param: String) {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))); "PragmaRepeatedMeasurement")]
 fn test_pyo3_is_parametrized(input_measurement: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    assert!(!bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        assert!(!bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 /// Test substitute_parameters function
@@ -338,30 +334,30 @@ fn test_pyo3_is_parametrized(input_measurement: Operation) {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))); "PragmaRepeatedMeasurement")]
 fn test_pyo3_substitute_parameters(input_measurement: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
-    substitution_dict.insert("ro", 1.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict,))
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
+        substitution_dict.insert("ro", 1.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict,))
+            .unwrap();
+        let substitute_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (substitute_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let substitute_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (substitute_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let mut substitution_dict_error = HashMap::new();
-    substitution_dict_error.insert("wrong", "fails");
-    let comparison =
-        substitute_op.call_method1(py, "substitute_parameters", (substitution_dict_error,));
-    assert!(comparison.is_err());
+        assert!(comparison_copy);
+
+        let mut substitution_dict_error = HashMap::new();
+        substitution_dict_error.insert("wrong", "fails");
+        let comparison =
+            substitute_op.call_method1(py, "substitute_parameters", (substitution_dict_error,));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test substitute_parameters() causing an error `not-a-real-number`
@@ -373,14 +369,14 @@ fn test_pyo3_substitute_parameters(input_measurement: Operation) {
 #[test_case(Operation::from(PragmaRepeatedMeasurement::new(String::from("ro"), 2, Some(create_qubit_mapping()))); "PragmaRepeatedMeasurement")]
 fn test_pyo3_substitute_params_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let mut substitution_dict: HashMap<&str, &str> = HashMap::new();
-    substitution_dict.insert("ro", "test");
-    let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let mut substitution_dict: HashMap<&str, &str> = HashMap::new();
+        substitution_dict.insert("ro", "test");
+        let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test remap_qubits function
@@ -404,28 +400,28 @@ fn test_pyo3_substitute_params_error(input_operation: Operation) {
             "PragmaRepeatedMeasurement")]
 fn test_pyo3_remap_qubits(first_op: Operation, second_op: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(first_op).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(first_op).unwrap();
 
-    let remapped_op = operation
-        .call_method1(py, "remap_qubits", (qubit_remapping(),))
+        let remapped_op = operation
+            .call_method1(py, "remap_qubits", (qubit_remapping(),))
+            .unwrap();
+        let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
+
+        let comparison = bool::extract(
+            remapped_op
+                .call_method1(py, "__eq__", (comparison_op,))
+                .unwrap()
+                .as_ref(py),
+        )
         .unwrap();
-    let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        remapped_op
-            .call_method1(py, "__eq__", (comparison_op,))
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let mut qubit_mapping_error = HashMap::new();
-    qubit_mapping_error.insert("fails", 3);
-    let comparison = operation.call_method1(py, "remap_qubits", (qubit_mapping_error,));
-    assert!(comparison.is_err());
+        let mut qubit_mapping_error = HashMap::new();
+        qubit_mapping_error.insert("fails", 3);
+        let comparison = operation.call_method1(py, "remap_qubits", (qubit_mapping_error,));
+        assert!(comparison.is_err());
+    })
 }
 
 // test remap_qubits() function returning an error.
@@ -433,14 +429,14 @@ fn test_pyo3_remap_qubits(first_op: Operation, second_op: Operation) {
 fn test_pyo3_remapqubits_error(input_operation: Operation) {
     // preparation
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    // remap qubits
-    let qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        // remap qubits
+        let qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test the __richcmp__ function
@@ -464,315 +460,316 @@ fn test_pyo3_remapqubits_error(input_operation: Operation) {
             "PragmaRepeatedMeasurement")]
 fn test_pyo3_richcmp(definition_1: Operation, definition_2: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
-    let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__eq__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(!comparison);
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__ne__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
-    assert!(comparison.is_err());
-
-    let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
-    assert!(comparison.is_err());
+    Python::with_gil(|py| -> () {
+        let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
+        let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__eq__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(!comparison);
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__ne__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+
+        let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
+        assert!(comparison.is_err());
+
+        let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test MeasureQubit new() function
 #[test]
 fn test_pyo3_new_set_number_of_measurements() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<MeasureQubitWrapper>();
-    let new_op = operation
-        .call1((0, "ro".to_string(), 1))
-        .unwrap()
-        .cast_as::<PyCell<MeasureQubitWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<MeasureQubitWrapper>();
+        let new_op = operation
+            .call1((0, "ro".to_string(), 1))
+            .unwrap()
+            .cast_as::<PyCell<MeasureQubitWrapper>>()
+            .unwrap();
 
-    let input_definition = Operation::from(MeasureQubit::new(0, String::from("ro"), 1));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let meas_wrapper = new_op.extract::<MeasureQubitWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((1, "ro".to_string(), 1))
-        .unwrap()
-        .cast_as::<PyCell<MeasureQubitWrapper>>()
+        let input_definition = Operation::from(MeasureQubit::new(0, String::from("ro"), 1));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let meas_wrapper_diff = new_op_diff.extract::<MeasureQubitWrapper>().unwrap();
-    let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", meas_wrapper),
-        "MeasureQubitWrapper { internal: MeasureQubit { qubit: 0, readout: \"ro\", readout_index: 1 } }"
-    );
+        assert!(comparison_copy);
+
+        let meas_wrapper = new_op.extract::<MeasureQubitWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((1, "ro".to_string(), 1))
+            .unwrap()
+            .cast_as::<PyCell<MeasureQubitWrapper>>()
+            .unwrap();
+        let meas_wrapper_diff = new_op_diff.extract::<MeasureQubitWrapper>().unwrap();
+        let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", meas_wrapper),
+            "MeasureQubitWrapper { internal: MeasureQubit { qubit: 0, readout: \"ro\", readout_index: 1 } }"
+        );
+    })
 }
 
 /// Test PragmaGetStateVector new() function
 #[test]
 fn test_pyo3_new_get_statevector() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaGetStateVectorWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), Option::<CircuitWrapper>::None))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGetStateVectorWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaGetStateVectorWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), Option::<CircuitWrapper>::None))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGetStateVectorWrapper>>()
+            .unwrap();
 
-    let input_definition = Operation::from(PragmaGetStateVector::new(String::from("ro"), None));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let meas_wrapper = new_op.extract::<PragmaGetStateVectorWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("ro2".to_string(), new_circuit(py)))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGetStateVectorWrapper>>()
-        .unwrap();
-    let meas_wrapper_diff = new_op_diff
-        .extract::<PragmaGetStateVectorWrapper>()
+        let input_definition = Operation::from(PragmaGetStateVector::new(String::from("ro"), None));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", meas_wrapper),
-        "PragmaGetStateVectorWrapper { internal: PragmaGetStateVector { readout: \"ro\", circuit: None } }"
-    );
+        assert!(comparison_copy);
+
+        let meas_wrapper = new_op.extract::<PragmaGetStateVectorWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("ro2".to_string(), new_circuit(py)))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGetStateVectorWrapper>>()
+            .unwrap();
+        let meas_wrapper_diff = new_op_diff
+            .extract::<PragmaGetStateVectorWrapper>()
+            .unwrap();
+        let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", meas_wrapper),
+            "PragmaGetStateVectorWrapper { internal: PragmaGetStateVector { readout: \"ro\", circuit: None } }"
+        );
+    })
 }
 
 /// Test PragmaGetDensityMatrix new() function
 #[test]
 fn test_pyo3_new_get_density_matrix() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaGetDensityMatrixWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), Option::<CircuitWrapper>::None))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGetDensityMatrixWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaGetDensityMatrixWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), Option::<CircuitWrapper>::None))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGetDensityMatrixWrapper>>()
+            .unwrap();
 
-    let input_definition = Operation::from(PragmaGetDensityMatrix::new(String::from("ro"), None));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let meas_wrapper = new_op.extract::<PragmaGetDensityMatrixWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("ro2".to_string(), new_circuit(py)))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGetDensityMatrixWrapper>>()
-        .unwrap();
-    let meas_wrapper_diff = new_op_diff
-        .extract::<PragmaGetDensityMatrixWrapper>()
+        let input_definition =
+            Operation::from(PragmaGetDensityMatrix::new(String::from("ro"), None));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", meas_wrapper),
-        "PragmaGetDensityMatrixWrapper { internal: PragmaGetDensityMatrix { readout: \"ro\", circuit: None } }"
-    );
+        assert!(comparison_copy);
+
+        let meas_wrapper = new_op.extract::<PragmaGetDensityMatrixWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("ro2".to_string(), new_circuit(py)))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGetDensityMatrixWrapper>>()
+            .unwrap();
+        let meas_wrapper_diff = new_op_diff
+            .extract::<PragmaGetDensityMatrixWrapper>()
+            .unwrap();
+        let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", meas_wrapper),
+            "PragmaGetDensityMatrixWrapper { internal: PragmaGetDensityMatrix { readout: \"ro\", circuit: None } }"
+        );
+    })
 }
 
 /// Test PragmaGetOccupationProbability new() function
 #[test]
 fn test_pyo3_new_get_occupation_proba() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaGetOccupationProbabilityWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), Option::<CircuitWrapper>::None))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGetOccupationProbabilityWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaGetOccupationProbabilityWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), Option::<CircuitWrapper>::None))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGetOccupationProbabilityWrapper>>()
+            .unwrap();
 
-    let input_definition = Operation::from(PragmaGetOccupationProbability::new(
-        String::from("ro"),
-        None,
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let meas_wrapper = new_op
-        .extract::<PragmaGetOccupationProbabilityWrapper>()
-        .unwrap();
-    let new_op_diff = operation
-        .call1(("ro2".to_string(), new_circuit(py)))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGetOccupationProbabilityWrapper>>()
-        .unwrap();
-    let meas_wrapper_diff = new_op_diff
-        .extract::<PragmaGetOccupationProbabilityWrapper>()
+        let input_definition = Operation::from(PragmaGetOccupationProbability::new(
+            String::from("ro"),
+            None,
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", meas_wrapper),
-        "PragmaGetOccupationProbabilityWrapper { internal: PragmaGetOccupationProbability { readout: \"ro\", circuit: None } }"
-    );
+        assert!(comparison_copy);
+
+        let meas_wrapper = new_op
+            .extract::<PragmaGetOccupationProbabilityWrapper>()
+            .unwrap();
+        let new_op_diff = operation
+            .call1(("ro2".to_string(), new_circuit(py)))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGetOccupationProbabilityWrapper>>()
+            .unwrap();
+        let meas_wrapper_diff = new_op_diff
+            .extract::<PragmaGetOccupationProbabilityWrapper>()
+            .unwrap();
+        let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", meas_wrapper),
+            "PragmaGetOccupationProbabilityWrapper { internal: PragmaGetOccupationProbability { readout: \"ro\", circuit: None } }"
+        );
+    })
 }
 
 /// Test PragmaGetPauliProduct new() function
 #[test]
 fn test_pyo3_new_get_pauli_product() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaGetPauliProductWrapper>();
-    let new_op = operation
-        .call1((create_qubit_mapping(), "ro".to_string(), new_circuit(py)))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGetPauliProductWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaGetPauliProductWrapper>();
+        let new_op = operation
+            .call1((create_qubit_mapping(), "ro".to_string(), new_circuit(py)))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGetPauliProductWrapper>>()
+            .unwrap();
 
-    let input_definition = Operation::from(PragmaGetPauliProduct::new(
-        create_qubit_mapping(),
-        String::from("ro"),
-        Circuit::default(),
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let meas_wrapper = new_op.extract::<PragmaGetPauliProductWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((create_qubit_mapping(), "ro2".to_string(), new_circuit(py)))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGetPauliProductWrapper>>()
-        .unwrap();
-    let meas_wrapper_diff = new_op_diff
-        .extract::<PragmaGetPauliProductWrapper>()
+        let input_definition = Operation::from(PragmaGetPauliProduct::new(
+            create_qubit_mapping(),
+            String::from("ro"),
+            Circuit::default(),
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", meas_wrapper),
-        "PragmaGetPauliProductWrapper { internal: PragmaGetPauliProduct { qubit_paulis: {0: 1}, readout: \"ro\", circuit: Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion } } }"
-    );
+        assert!(comparison_copy);
+
+        let meas_wrapper = new_op.extract::<PragmaGetPauliProductWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((create_qubit_mapping(), "ro2".to_string(), new_circuit(py)))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGetPauliProductWrapper>>()
+            .unwrap();
+        let meas_wrapper_diff = new_op_diff
+            .extract::<PragmaGetPauliProductWrapper>()
+            .unwrap();
+        let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", meas_wrapper),
+            "PragmaGetPauliProductWrapper { internal: PragmaGetPauliProduct { qubit_paulis: {0: 1}, readout: \"ro\", circuit: Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion } } }"
+        );
+    })
 }
 
 /// Test PragmaRepeatedMeasurement new() function
 #[test]
 fn test_pyo3_new_repeated_measurement() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaRepeatedMeasurementWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), 1, Some(create_qubit_mapping())))
-        .unwrap()
-        .cast_as::<PyCell<PragmaRepeatedMeasurementWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaRepeatedMeasurementWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), 1, Some(create_qubit_mapping())))
+            .unwrap()
+            .cast_as::<PyCell<PragmaRepeatedMeasurementWrapper>>()
+            .unwrap();
 
-    let input_definition = Operation::from(PragmaRepeatedMeasurement::new(
-        String::from("ro"),
-        1,
-        Some(create_qubit_mapping()),
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let meas_wrapper = new_op
-        .extract::<PragmaRepeatedMeasurementWrapper>()
-        .unwrap();
-    let new_op_diff = operation
-        .call1(("ro".to_string(), 2, Some(create_qubit_mapping())))
-        .unwrap()
-        .cast_as::<PyCell<PragmaRepeatedMeasurementWrapper>>()
-        .unwrap();
-    let meas_wrapper_diff = new_op_diff
-        .extract::<PragmaRepeatedMeasurementWrapper>()
+        let input_definition = Operation::from(PragmaRepeatedMeasurement::new(
+            String::from("ro"),
+            1,
+            Some(create_qubit_mapping()),
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", meas_wrapper),
-        "PragmaRepeatedMeasurementWrapper { internal: PragmaRepeatedMeasurement { readout: \"ro\", number_measurements: 1, qubit_mapping: Some({0: 1}) } }"
-    );
+        assert!(comparison_copy);
+
+        let meas_wrapper = new_op
+            .extract::<PragmaRepeatedMeasurementWrapper>()
+            .unwrap();
+        let new_op_diff = operation
+            .call1(("ro".to_string(), 2, Some(create_qubit_mapping())))
+            .unwrap()
+            .cast_as::<PyCell<PragmaRepeatedMeasurementWrapper>>()
+            .unwrap();
+        let meas_wrapper_diff = new_op_diff
+            .extract::<PragmaRepeatedMeasurementWrapper>()
+            .unwrap();
+        let helper_ne: bool = meas_wrapper_diff != meas_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = meas_wrapper == meas_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", meas_wrapper),
+            "PragmaRepeatedMeasurementWrapper { internal: PragmaRepeatedMeasurement { readout: \"ro\", number_measurements: 1, qubit_mapping: Some({0: 1}) } }"
+        );
+    })
 }
diff --git a/qoqo/tests/integration/operations/multi_qubit_gate_operations.rs b/qoqo/tests/integration/operations/multi_qubit_gate_operations.rs
index 57571ad8..0cc3802e 100644
--- a/qoqo/tests/integration/operations/multi_qubit_gate_operations.rs
+++ b/qoqo/tests/integration/operations/multi_qubit_gate_operations.rs
@@ -53,79 +53,78 @@ fn convert_cf_to_pyobject(
 fn test_new_multi_qubit_ms(input_operation: Operation, arguments: (Vec<u32>, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<MultiQubitMSWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<MultiQubitMSWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1(([0, 1], vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<MultiQubitMSWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((vec![1, 2], 0.0))
-        .unwrap()
-        .cast_as::<PyCell<MultiQubitMSWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<MultiQubitMSWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<MultiQubitMSWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<MultiQubitMSWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "MultiQubitMSWrapper { internal: MultiQubitMS { qubits: [1, 2], theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1(([0, 1], vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<MultiQubitMSWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((vec![1, 2], 0.0))
+            .unwrap()
+            .cast_as::<PyCell<MultiQubitMSWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<MultiQubitMSWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "MultiQubitMSWrapper { internal: MultiQubitMS { qubits: [1, 2], theta: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test is_parametrized() function for MultiQubitGate Operations
 #[test_case(Operation::from(MultiQubitMS::new(vec![0, 1], CalculatorFloat::from("theta"))); "MultiQubitMS")]
 fn test_pyo3_is_parametrized(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    assert!(bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        assert!(bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 /// Test is_parametrized = false for MultiQubitGate Operations
 #[test_case(Operation::from(MultiQubitMS::new(vec![0, 1], CalculatorFloat::PI)); "MultiQubitMS")]
 fn test_pyo3_is_not_parametrized(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    assert!(!bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        assert!(!bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 /// Test theta() function for Rotations
@@ -133,15 +132,16 @@ fn test_pyo3_is_not_parametrized(input_operation: Operation) {
 #[test_case(CalculatorFloat::from("theta"), Operation::from(MultiQubitMS::new(vec![0, 1], CalculatorFloat::from("theta"))); "MultiQubitMS symb")]
 fn test_pyo3_theta(theta: CalculatorFloat, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let theta_op: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(operation.call_method0(py, "theta").unwrap().as_ref(py))
-            .unwrap();
-    let theta_param: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, theta)).unwrap();
-    assert_eq!(theta_op.cf_internal, theta_param.cf_internal);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let theta_op: CalculatorFloatWrapper = CalculatorFloatWrapper::extract(
+            operation.call_method0(py, "theta").unwrap().as_ref(py),
+        )
+        .unwrap();
+        let theta_param: CalculatorFloatWrapper =
+            CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, theta)).unwrap();
+        assert_eq!(theta_op.cf_internal, theta_param.cf_internal);
+    })
 }
 
 /// Test qubits() function for MultiQubitGate Operations
@@ -149,28 +149,28 @@ fn test_pyo3_theta(theta: CalculatorFloat, input_operation: Operation) {
 #[test_case(vec![0, 1, 2], Operation::from(MultiQubitMS::new(vec![0, 1, 2], CalculatorFloat::from(0))); "MultiQubitMS three")]
 fn test_pyo3_qubits(qubit: Vec<usize>, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let qubit_op: Vec<usize> = operation
-        .call_method0(py, "qubits")
-        .unwrap()
-        .as_ref(py)
-        .extract()
-        .unwrap();
-    assert_eq!(qubit_op, qubit);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let qubit_op: Vec<usize> = operation
+            .call_method0(py, "qubits")
+            .unwrap()
+            .as_ref(py)
+            .extract()
+            .unwrap();
+        assert_eq!(qubit_op, qubit);
+    })
 }
 
 /// Test hqslang() function for MultiQubitGate Operations
 #[test_case("MultiQubitMS", Operation::from(MultiQubitMS::new(vec![0, 1], CalculatorFloat::from(0))); "MultiQubitMS")]
 fn test_pyo3_hqslang(name: &'static str, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let name_op: String =
-        String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
-    assert_eq!(name_op, name.to_string());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let name_op: String =
+            String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
+        assert_eq!(name_op, name.to_string());
+    })
 }
 
 /// Test tags() function for MultiQubitGate Operations
@@ -186,50 +186,50 @@ fn test_pyo3_hqslang(name: &'static str, input_operation: Operation) {
     "MultiQubitMS")]
 fn test_pyo3_tags(input_operation: Operation, tags: Vec<&str>) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let tags_op: Vec<String> =
-        Vec::<String>::extract(operation.call_method0(py, "tags").unwrap().as_ref(py)).unwrap();
-    assert_eq!(tags_op.len(), tags.len());
-    for i in 0..tags.len() {
-        assert_eq!(tags_op[i], tags[i]);
-    }
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let tags_op: Vec<String> =
+            Vec::<String>::extract(operation.call_method0(py, "tags").unwrap().as_ref(py)).unwrap();
+        assert_eq!(tags_op.len(), tags.len());
+        for i in 0..tags.len() {
+            assert_eq!(tags_op[i], tags[i]);
+        }
+    })
 }
 
 /// Test remap_qubits() function for MultiQubitGate Operations
 #[test_case(Operation::from(MultiQubitMS::new(vec![0, 1, 2], CalculatorFloat::from(1.3))); "MultiQubitMS")]
 fn test_pyo3_remapqubits(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    // test initial qubit
-    let qubits: Vec<usize> = operation
-        .call_method0(py, "qubits")
-        .unwrap()
-        .as_ref(py)
-        .extract()
-        .unwrap();
-    assert_eq!(qubits.clone(), vec![0, 1, 2]);
-    // remap qubits
-    let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    qubit_mapping.insert(0, 1);
-    qubit_mapping.insert(1, 2);
-    qubit_mapping.insert(2, 0);
-    let result = operation
-        .call_method1(py, "remap_qubits", (qubit_mapping,))
-        .unwrap();
-    // test re-mapped qubit
-    let qubits_new: Vec<usize> = result
-        .call_method0(py, "qubits")
-        .unwrap()
-        .as_ref(py)
-        .extract()
-        .unwrap();
-    assert_eq!(qubits_new.clone(), vec![1, 2, 0]);
-    // test that initial and rempapped qubits are different
-    assert_ne!(qubits, qubits_new);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        // test initial qubit
+        let qubits: Vec<usize> = operation
+            .call_method0(py, "qubits")
+            .unwrap()
+            .as_ref(py)
+            .extract()
+            .unwrap();
+        assert_eq!(qubits.clone(), vec![0, 1, 2]);
+        // remap qubits
+        let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        qubit_mapping.insert(0, 1);
+        qubit_mapping.insert(1, 2);
+        qubit_mapping.insert(2, 0);
+        let result = operation
+            .call_method1(py, "remap_qubits", (qubit_mapping,))
+            .unwrap();
+        // test re-mapped qubit
+        let qubits_new: Vec<usize> = result
+            .call_method0(py, "qubits")
+            .unwrap()
+            .as_ref(py)
+            .extract()
+            .unwrap();
+        assert_eq!(qubits_new.clone(), vec![1, 2, 0]);
+        // test that initial and rempapped qubits are different
+        assert_ne!(qubits, qubits_new);
+    })
 }
 
 // test remap_qubits() function returning an error.
@@ -237,104 +237,104 @@ fn test_pyo3_remapqubits(input_operation: Operation) {
 fn test_pyo3_remapqubits_error(input_operation: Operation) {
     // preparation
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    // remap qubits
-    let qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        // remap qubits
+        let qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test unitary_matrix() function for MultiQubitGate Operations
 #[test_case(Operation::from(MultiQubitMS::new(vec![0, 1, 2], CalculatorFloat::from(1.3))); "MultiQubitMS")]
 fn test_pyo3_unitarymatrix(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let py_result = operation.call_method0(py, "unitary_matrix").unwrap();
-    let result_matrix = py_result
-        .cast_as::<PyArray2<Complex64>>(py)
-        .unwrap()
-        .to_owned_array();
-
-    // compare to reference matrix obtained in Rust directly (without passing to Python)
-    let gate: MultiQubitGateOperation = input_operation.try_into().unwrap();
-    let rust_matrix: Result<Array2<Complex64>, RoqoqoError> = gate.unitary_matrix();
-    let test_matrix: Array2<Complex64> = rust_matrix.unwrap();
-
-    assert_eq!(result_matrix, test_matrix);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let py_result = operation.call_method0(py, "unitary_matrix").unwrap();
+        let result_matrix = py_result
+            .cast_as::<PyArray2<Complex64>>(py)
+            .unwrap()
+            .to_owned_array();
+
+        // compare to reference matrix obtained in Rust directly (without passing to Python)
+        let gate: MultiQubitGateOperation = input_operation.try_into().unwrap();
+        let rust_matrix: Result<Array2<Complex64>, RoqoqoError> = gate.unitary_matrix();
+        let test_matrix: Array2<Complex64> = rust_matrix.unwrap();
+
+        assert_eq!(result_matrix, test_matrix);
+    })
 }
 
 /// Test unitary_matrix() function for MultiQubitGate Operations for the error case
 #[test_case(Operation::from(MultiQubitMS::new(vec![0, 1, 2], CalculatorFloat::from("PI"))); "MultiQubitMS")]
 fn test_pyo3_unitarymatrix_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let py_result = operation.call_method0(py, "unitary_matrix");
-    let result_ref = py_result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let py_result = operation.call_method0(py, "unitary_matrix");
+        let result_ref = py_result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test circuit() function for MultiQubitMS
 #[test]
 fn test_pyo3_circuit_ms() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let input_operation =
-        Operation::from(MultiQubitMS::new(vec![0, 1, 2], CalculatorFloat::from(1.0)));
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let py_result = operation.call_method0(py, "circuit").unwrap();
-    let result_circuit: CircuitWrapper = py_result.extract(py).unwrap();
-
-    let mut circuit = Circuit::new();
-    circuit += Hadamard::new(0);
-    circuit += Hadamard::new(1);
-    circuit += Hadamard::new(2);
-    circuit += CNOT::new(0, 1);
-    circuit += CNOT::new(1, 2);
-    circuit += RotateZ::new(2, CalculatorFloat::from(0.5));
-    circuit += CNOT::new(1, 2);
-    circuit += CNOT::new(0, 1);
-    circuit += Hadamard::new(0);
-    circuit += Hadamard::new(1);
-    circuit += Hadamard::new(2);
-
-    assert_eq!(result_circuit.internal, circuit);
+    Python::with_gil(|py| -> () {
+        let input_operation =
+            Operation::from(MultiQubitMS::new(vec![0, 1, 2], CalculatorFloat::from(1.0)));
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let py_result = operation.call_method0(py, "circuit").unwrap();
+        let result_circuit: CircuitWrapper = py_result.extract(py).unwrap();
+
+        let mut circuit = Circuit::new();
+        circuit += Hadamard::new(0);
+        circuit += Hadamard::new(1);
+        circuit += Hadamard::new(2);
+        circuit += CNOT::new(0, 1);
+        circuit += CNOT::new(1, 2);
+        circuit += RotateZ::new(2, CalculatorFloat::from(0.5));
+        circuit += CNOT::new(1, 2);
+        circuit += CNOT::new(0, 1);
+        circuit += Hadamard::new(0);
+        circuit += Hadamard::new(1);
+        circuit += Hadamard::new(2);
+
+        assert_eq!(result_circuit.internal, circuit);
+    })
 }
 
 /// Test copy and deepcopy functions
 #[test_case(Operation::from(MultiQubitMS::new(vec![0, 1, 2], CalculatorFloat::from(1.3))); "MultiQubitMS")]
 fn test_pyo3_copy_deepcopy(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let copy_op = operation.call_method0(py, "__copy__").unwrap();
-    let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
-    let copy_deepcopy_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        copy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-    let comparison_deepcopy = bool::extract(
-        deepcopy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let copy_op = operation.call_method0(py, "__copy__").unwrap();
+        let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
+        let copy_deepcopy_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            copy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+        let comparison_deepcopy = bool::extract(
+            deepcopy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 /// Test format and repr functions
@@ -344,58 +344,58 @@ fn test_pyo3_copy_deepcopy(input_operation: Operation) {
     "MultiQubitMS")]
 fn test_pyo3_format_repr(format_repr: &str, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-    assert_eq!(format_op, format_repr);
-    let to_repr = operation.call_method0(py, "__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-    assert_eq!(repr_op, format_repr);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+        assert_eq!(format_op, format_repr);
+        let to_repr = operation.call_method0(py, "__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+        assert_eq!(repr_op, format_repr);
+    })
 }
 
 /// Test substitute_parameters() function for one parameter
 #[test_case(Operation::from(MultiQubitMS::new(vec![1, 2, 3], CalculatorFloat::from("theta"))); "MultiQubitMS")]
 fn test_pyo3_substitute_params_rotate(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let mut substitution_dict_py: HashMap<&str, f64> = HashMap::new();
-    substitution_dict_py.insert("theta", 1.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict_py,))
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let mut substitution_dict_py: HashMap<&str, f64> = HashMap::new();
+        substitution_dict_py.insert("theta", 1.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict_py,))
+            .unwrap();
 
-    let mut substitution_dict: Calculator = Calculator::new();
-    substitution_dict.set_variable("theta", 1.0);
-    let substitute_param = input_operation
-        .substitute_parameters(&mut substitution_dict)
+        let mut substitution_dict: Calculator = Calculator::new();
+        substitution_dict.set_variable("theta", 1.0);
+        let substitute_param = input_operation
+            .substitute_parameters(&mut substitution_dict)
+            .unwrap();
+        let test_operation = convert_operation_to_pyobject(substitute_param).unwrap();
+
+        let comparison = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (test_operation.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let test_operation = convert_operation_to_pyobject(substitute_param).unwrap();
-
-    let comparison = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (test_operation.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        assert!(comparison);
+    })
 }
 
 /// Test substitute_parameters() causing an error `None`
 #[test_case(Operation::from(MultiQubitMS::new(vec![1, 2], CalculatorFloat::from("test"))); "MultiQubitMS")]
 fn test_pyo3_substitute_params_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let substitution_dict: HashMap<&str, f64> = HashMap::new();
-    let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let substitution_dict: HashMap<&str, f64> = HashMap::new();
+        let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 #[test_case(
@@ -403,22 +403,22 @@ fn test_pyo3_substitute_params_error(input_operation: Operation) {
     Operation::from(MultiQubitMS::new(vec![0, 1, 2], CalculatorFloat::from(0.005 * 1.5))); "MultiQubitMS")]
 fn test_pyo3_rotate_powercf(first_op: Operation, second_op: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(first_op).unwrap();
-
-    let power = convert_cf_to_pyobject(py, CalculatorFloat::from(1.5));
-    let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
-
-    let remapped_op = operation.call_method1(py, "powercf", (power,)).unwrap();
-    let comparison = bool::extract(
-        remapped_op
-            .call_method1(py, "__eq__", (comparison_op,))
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(first_op).unwrap();
+
+        let power = convert_cf_to_pyobject(py, CalculatorFloat::from(1.5));
+        let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
+
+        let remapped_op = operation.call_method1(py, "powercf", (power,)).unwrap();
+        let comparison = bool::extract(
+            remapped_op
+                .call_method1(py, "__eq__", (comparison_op,))
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 /// Test the __richcmp__ function
@@ -427,32 +427,32 @@ fn test_pyo3_rotate_powercf(first_op: Operation, second_op: Operation) {
     Operation::from(MultiQubitMS::new(vec![1, 2], CalculatorFloat::from(0))); "MultiQubitMS")]
 fn test_pyo3_richcmp(definition_1: Operation, definition_2: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
-    let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__eq__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(!comparison);
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__ne__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
+        let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__eq__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(!comparison);
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__ne__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
 
-    let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
+        assert!(comparison.is_err());
 
-    let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
+        assert!(comparison.is_err());
+    })
 }
diff --git a/qoqo/tests/integration/operations/operation_conversions.rs b/qoqo/tests/integration/operations/operation_conversions.rs
index 785fdb7e..ccc1c3e5 100644
--- a/qoqo/tests/integration/operations/operation_conversions.rs
+++ b/qoqo/tests/integration/operations/operation_conversions.rs
@@ -12,6 +12,7 @@
 
 use ndarray::{array, Array1, Array2};
 use num_complex::Complex64;
+use pyo3::Python;
 use qoqo::operations::*;
 use qoqo_calculator::CalculatorFloat;
 use roqoqo::operations::*;
@@ -103,11 +104,11 @@ use test_case::test_case;
 #[test_case(Operation::from(PragmaConditional::new(String::from("ro"), 1, create_circuit())); "PragmaConditional")]
 fn test_conversion(input: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input.clone()).unwrap();
-    let output = convert_pyany_to_operation(operation.as_ref(py)).unwrap();
-    assert_eq!(input, output)
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input.clone()).unwrap();
+        let output = convert_pyany_to_operation(operation.as_ref(py)).unwrap();
+        assert_eq!(input, output)
+    })
 }
 
 // ---------------- Helper functions ---------------- //
diff --git a/qoqo/tests/integration/operations/pragma_operations.rs b/qoqo/tests/integration/operations/pragma_operations.rs
index b2228ec8..3d9d5123 100644
--- a/qoqo/tests/integration/operations/pragma_operations.rs
+++ b/qoqo/tests/integration/operations/pragma_operations.rs
@@ -14,6 +14,7 @@ use ndarray::{arr2, array, Array, Array1, Array2};
 use num_complex::Complex64;
 use numpy::PyArray2;
 use pyo3::prelude::*;
+use pyo3::Python;
 use qoqo::operations::*;
 use qoqo::CircuitWrapper;
 use qoqo_calculator::CalculatorFloat;
@@ -116,24 +117,24 @@ fn new_circuit(py: Python) -> &PyCell<CircuitWrapper> {
 fn test_pyo3_inputs_setnumbermeasurements() {
     let input_pragma = Operation::from(PragmaSetNumberOfMeasurements::new(1, String::from("ro")));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let nbr_meas_op: &usize = &usize::extract(
-        operation
-            .call_method0(py, "number_measurements")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    let nbr_meas_param: &usize = &1_usize;
-    assert_eq!(nbr_meas_op, nbr_meas_param);
+        let nbr_meas_op: &usize = &usize::extract(
+            operation
+                .call_method0(py, "number_measurements")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        let nbr_meas_param: &usize = &1_usize;
+        assert_eq!(nbr_meas_op, nbr_meas_param);
 
-    let readout_op: &String =
-        &String::extract(operation.call_method0(py, "readout").unwrap().as_ref(py)).unwrap();
-    let readout_param: &String = &String::from("ro");
-    assert_eq!(readout_op, readout_param);
+        let readout_op: &String =
+            &String::extract(operation.call_method0(py, "readout").unwrap().as_ref(py)).unwrap();
+        let readout_param: &String = &String::from("ro");
+        assert_eq!(readout_op, readout_param);
+    })
 }
 
 /// Test inputs of PragmaSetStateVector
@@ -141,19 +142,19 @@ fn test_pyo3_inputs_setnumbermeasurements() {
 fn test_pyo3_inputs_setstatevector() {
     let input_pragma = Operation::from(PragmaSetStateVector::new(statevector()));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let to_statevector_op: Vec<Complex64> = Vec::extract(
-        operation
-            .call_method0(py, "statevector")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    let statevector_op: Array1<Complex64> = Array1::from(to_statevector_op);
-    assert_eq!(statevector_op, statevector());
+        let to_statevector_op: Vec<Complex64> = Vec::extract(
+            operation
+                .call_method0(py, "statevector")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        let statevector_op: Array1<Complex64> = Array1::from(to_statevector_op);
+        assert_eq!(statevector_op, statevector());
+    })
 }
 
 /// Test inputs of PragmaSetDensityMatrix
@@ -161,19 +162,19 @@ fn test_pyo3_inputs_setstatevector() {
 fn test_pyo3_inputs_setdensitymatrix() {
     let input_pragma = Operation::from(PragmaSetDensityMatrix::new(densitymatrix()));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let to_operators_op: Vec<Complex64> = Vec::extract(
-        operation
-            .call_method0(py, "density_matrix")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    let operators_op = Array::from_shape_vec((2, 2), to_operators_op).unwrap();
-    assert_eq!(operators_op, densitymatrix());
+        let to_operators_op: Vec<Complex64> = Vec::extract(
+            operation
+                .call_method0(py, "density_matrix")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        let operators_op = Array::from_shape_vec((2, 2), to_operators_op).unwrap();
+        assert_eq!(operators_op, densitymatrix());
+    })
 }
 
 /// Test inputs of PragmaRepeatGate
@@ -181,18 +182,18 @@ fn test_pyo3_inputs_setdensitymatrix() {
 fn test_pyo3_inputs_repeatgate() {
     let input_pragma = Operation::from(PragmaRepeatGate::new(3));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let repeat_op: &usize = &usize::extract(
-        operation
-            .call_method0(py, "repetition_coefficient")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(repeat_op, &3_usize);
+        let repeat_op: &usize = &usize::extract(
+            operation
+                .call_method0(py, "repetition_coefficient")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(repeat_op, &3_usize);
+    })
 }
 
 /// Test inputs of PragmaOverrotation
@@ -205,27 +206,27 @@ fn test_pyo3_inputs_overrotation() {
         0.001,
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let string_op: &String = &String::extract(
-        operation
-            .call_method0(py, "gate_hqslang")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(string_op, &"RotateX".to_string());
-    let qubits_op: &Vec<usize> =
-        &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
-    assert_eq!(qubits_op, &vec![0]);
-    let amp_op: &f64 =
-        &f64::extract(operation.call_method0(py, "amplitude").unwrap().as_ref(py)).unwrap();
-    assert_eq!(amp_op, &0.03);
-    let var_op: &f64 =
-        &f64::extract(operation.call_method0(py, "variance").unwrap().as_ref(py)).unwrap();
-    assert_eq!(var_op, &0.001);
+        let string_op: &String = &String::extract(
+            operation
+                .call_method0(py, "gate_hqslang")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(string_op, &"RotateX".to_string());
+        let qubits_op: &Vec<usize> =
+            &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
+        assert_eq!(qubits_op, &vec![0]);
+        let amp_op: &f64 =
+            &f64::extract(operation.call_method0(py, "amplitude").unwrap().as_ref(py)).unwrap();
+        assert_eq!(amp_op, &0.03);
+        let var_op: &f64 =
+            &f64::extract(operation.call_method0(py, "variance").unwrap().as_ref(py)).unwrap();
+        assert_eq!(var_op, &0.001);
+    })
 }
 
 /// Test inputs of PragmaBoostNoise
@@ -233,21 +234,21 @@ fn test_pyo3_inputs_overrotation() {
 fn test_pyo3_inputs_boostnoise() {
     let input_pragma = Operation::from(PragmaBoostNoise::new(CalculatorFloat::from(0.003)));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let boost_op: &f64 = &f64::extract(
-        operation
-            .call_method0(py, "noise_coefficient")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(
-        CalculatorFloat::from(boost_op),
-        CalculatorFloat::from(0.003),
-    );
+        let boost_op: &f64 = &f64::extract(
+            operation
+                .call_method0(py, "noise_coefficient")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(
+            CalculatorFloat::from(boost_op),
+            CalculatorFloat::from(0.003),
+        );
+    })
 }
 
 /// Test inputs of PragmaStopParallelBlock
@@ -258,26 +259,26 @@ fn test_pyo3_inputs_stop() {
         CalculatorFloat::from(0.0000001),
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let qubits_op: &Vec<usize> =
-        &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
-    let qubits_param: Vec<usize> = vec![0, 1];
-    assert_eq!(qubits_op, &qubits_param);
+        let qubits_op: &Vec<usize> =
+            &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
+        let qubits_param: Vec<usize> = vec![0, 1];
+        assert_eq!(qubits_op, &qubits_param);
 
-    let boost_op: &f64 = &f64::extract(
-        operation
-            .call_method0(py, "execution_time")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(
-        CalculatorFloat::from(boost_op),
-        CalculatorFloat::from(0.0000001),
-    );
+        let boost_op: &f64 = &f64::extract(
+            operation
+                .call_method0(py, "execution_time")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(
+            CalculatorFloat::from(boost_op),
+            CalculatorFloat::from(0.0000001),
+        );
+    })
 }
 
 /// Test inputs of PragmaGlobalPhase
@@ -285,13 +286,13 @@ fn test_pyo3_inputs_stop() {
 fn test_pyo3_inputs_globalphase() {
     let input_pragma = Operation::from(PragmaGlobalPhase::new(CalculatorFloat::from(0.05)));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let boost_op: &f64 =
-        &f64::extract(operation.call_method0(py, "phase").unwrap().as_ref(py)).unwrap();
-    assert_eq!(CalculatorFloat::from(boost_op), CalculatorFloat::from(0.05));
+        let boost_op: &f64 =
+            &f64::extract(operation.call_method0(py, "phase").unwrap().as_ref(py)).unwrap();
+        assert_eq!(CalculatorFloat::from(boost_op), CalculatorFloat::from(0.05));
+    })
 }
 
 /// Test inputs of PragmaSleep
@@ -302,21 +303,21 @@ fn test_pyo3_inputs_sleep() {
         CalculatorFloat::from(0.0000001),
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let qubits_op: &Vec<usize> =
-        &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
-    let qubits_param: Vec<usize> = vec![0, 1];
-    assert_eq!(qubits_op, &qubits_param);
+        let qubits_op: &Vec<usize> =
+            &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
+        let qubits_param: Vec<usize> = vec![0, 1];
+        assert_eq!(qubits_op, &qubits_param);
 
-    let boost_op: &f64 =
-        &f64::extract(operation.call_method0(py, "sleep_time").unwrap().as_ref(py)).unwrap();
-    assert_eq!(
-        CalculatorFloat::from(boost_op),
-        CalculatorFloat::from(0.0000001),
-    );
+        let boost_op: &f64 =
+            &f64::extract(operation.call_method0(py, "sleep_time").unwrap().as_ref(py)).unwrap();
+        assert_eq!(
+            CalculatorFloat::from(boost_op),
+            CalculatorFloat::from(0.0000001),
+        );
+    })
 }
 
 /// Test inputs of PragmaActiveReset
@@ -324,14 +325,14 @@ fn test_pyo3_inputs_sleep() {
 fn test_pyo3_inputs_activereset() {
     let input_pragma = Operation::from(PragmaActiveReset::new(0));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let qubit_op: &usize =
-        &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
-    let qubit_param: &usize = &0_usize;
-    assert_eq!(qubit_op, qubit_param);
+        let qubit_op: &usize =
+            &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
+        let qubit_param: &usize = &0_usize;
+        assert_eq!(qubit_op, qubit_param);
+    })
 }
 
 /// Test inputs of PragmaStartDecompositionBlock
@@ -340,23 +341,23 @@ fn test_pyo3_inputs_startdecompblock() {
     let input_pragma =
         Operation::from(PragmaStartDecompositionBlock::new(vec![0, 1], reordering()));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let qubits_op: &Vec<usize> =
-        &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
-    let qubits_param: Vec<usize> = vec![0, 1];
-    assert_eq!(qubits_op, &qubits_param);
+        let qubits_op: &Vec<usize> =
+            &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
+        let qubits_param: Vec<usize> = vec![0, 1];
+        assert_eq!(qubits_op, &qubits_param);
 
-    let boost_op: HashMap<usize, usize> = HashMap::extract(
-        operation
-            .call_method0(py, "reordering_dictionary")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(boost_op, reordering());
+        let boost_op: HashMap<usize, usize> = HashMap::extract(
+            operation
+                .call_method0(py, "reordering_dictionary")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(boost_op, reordering());
+    })
 }
 
 /// Test inputs of PragmaStopDecompositionBlock
@@ -364,14 +365,14 @@ fn test_pyo3_inputs_startdecompblock() {
 fn test_pyo3_inputs_stopdecompblock() {
     let input_pragma = Operation::from(PragmaStopDecompositionBlock::new(vec![0, 1]));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let qubits_op: &Vec<usize> =
-        &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
-    let qubits_param: Vec<usize> = vec![0, 1];
-    assert_eq!(qubits_op, &qubits_param);
+        let qubits_op: &Vec<usize> =
+            &Vec::extract(operation.call_method0(py, "qubits").unwrap().as_ref(py)).unwrap();
+        let qubits_param: Vec<usize> = vec![0, 1];
+        assert_eq!(qubits_op, &qubits_param);
+    })
 }
 
 /// Test inputs of Noise Pragmas (except RandomNoise)
@@ -380,25 +381,25 @@ fn test_pyo3_inputs_stopdecompblock() {
 #[test_case(Operation::from(PragmaDephasing::new(0, CalculatorFloat::from(0.005), CalculatorFloat::from(0.02))); "PragmaDephasing")]
 fn test_pyo3_inputs_noise(input_pragma: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let qubit_op: &usize =
-        &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
-    let qubit_param: &usize = &0_usize;
-    assert_eq!(qubit_op, qubit_param);
+        let qubit_op: &usize =
+            &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
+        let qubit_param: &usize = &0_usize;
+        assert_eq!(qubit_op, qubit_param);
 
-    let gate_time_op: &f64 =
-        &f64::extract(operation.call_method0(py, "gate_time").unwrap().as_ref(py)).unwrap();
-    assert_eq!(
-        CalculatorFloat::from(gate_time_op),
-        CalculatorFloat::from(0.005),
-    );
+        let gate_time_op: &f64 =
+            &f64::extract(operation.call_method0(py, "gate_time").unwrap().as_ref(py)).unwrap();
+        assert_eq!(
+            CalculatorFloat::from(gate_time_op),
+            CalculatorFloat::from(0.005),
+        );
 
-    let rate_op: &f64 =
-        &f64::extract(operation.call_method0(py, "rate").unwrap().as_ref(py)).unwrap();
-    assert_eq!(CalculatorFloat::from(rate_op), CalculatorFloat::from(0.02));
+        let rate_op: &f64 =
+            &f64::extract(operation.call_method0(py, "rate").unwrap().as_ref(py)).unwrap();
+        assert_eq!(CalculatorFloat::from(rate_op), CalculatorFloat::from(0.02));
+    })
 }
 
 /// Test inputs of PragmaRandomNoise
@@ -411,45 +412,45 @@ fn test_pyo3_inputs_randomnoise() {
         CalculatorFloat::from(0.01),
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
-
-    let qubit_op: &usize =
-        &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
-    let qubit_param: &usize = &0_usize;
-    assert_eq!(qubit_op, qubit_param);
-
-    let gate_time_op: &f64 =
-        &f64::extract(operation.call_method0(py, "gate_time").unwrap().as_ref(py)).unwrap();
-    assert_eq!(
-        CalculatorFloat::from(gate_time_op),
-        CalculatorFloat::from(0.005),
-    );
-
-    let depol_rate_op: &f64 = &f64::extract(
-        operation
-            .call_method0(py, "depolarising_rate")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(
-        CalculatorFloat::from(depol_rate_op),
-        CalculatorFloat::from(0.02)
-    );
-
-    let dephas_rate_op: &f64 = &f64::extract(
-        operation
-            .call_method0(py, "dephasing_rate")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(
-        CalculatorFloat::from(dephas_rate_op),
-        CalculatorFloat::from(0.01)
-    );
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+
+        let qubit_op: &usize =
+            &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
+        let qubit_param: &usize = &0_usize;
+        assert_eq!(qubit_op, qubit_param);
+
+        let gate_time_op: &f64 =
+            &f64::extract(operation.call_method0(py, "gate_time").unwrap().as_ref(py)).unwrap();
+        assert_eq!(
+            CalculatorFloat::from(gate_time_op),
+            CalculatorFloat::from(0.005),
+        );
+
+        let depol_rate_op: &f64 = &f64::extract(
+            operation
+                .call_method0(py, "depolarising_rate")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(
+            CalculatorFloat::from(depol_rate_op),
+            CalculatorFloat::from(0.02)
+        );
+
+        let dephas_rate_op: &f64 = &f64::extract(
+            operation
+                .call_method0(py, "dephasing_rate")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(
+            CalculatorFloat::from(dephas_rate_op),
+            CalculatorFloat::from(0.01)
+        );
+    })
 }
 
 /// Test inputs of PragmaGeneralNoise
@@ -461,26 +462,26 @@ fn test_pyo3_inputs_generalnoise() {
         operators(),
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let qubit_op: &usize =
-        &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
-    let qubit_param: &usize = &0_usize;
-    assert_eq!(qubit_op, qubit_param);
+        let qubit_op: &usize =
+            &usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
+        let qubit_param: &usize = &0_usize;
+        assert_eq!(qubit_op, qubit_param);
 
-    let gate_time_op: &f64 =
-        &f64::extract(operation.call_method0(py, "gate_time").unwrap().as_ref(py)).unwrap();
-    assert_eq!(
-        CalculatorFloat::from(gate_time_op),
-        CalculatorFloat::from(0.005),
-    );
+        let gate_time_op: &f64 =
+            &f64::extract(operation.call_method0(py, "gate_time").unwrap().as_ref(py)).unwrap();
+        assert_eq!(
+            CalculatorFloat::from(gate_time_op),
+            CalculatorFloat::from(0.005),
+        );
 
-    let to_operators_op: Vec<f64> =
-        Vec::extract(operation.call_method0(py, "rates").unwrap().as_ref(py)).unwrap();
-    let operators_op = Array::from_shape_vec((3, 3), to_operators_op).unwrap();
-    assert_eq!(operators_op, operators());
+        let to_operators_op: Vec<f64> =
+            Vec::extract(operation.call_method0(py, "rates").unwrap().as_ref(py)).unwrap();
+        let operators_op = Array::from_shape_vec((3, 3), to_operators_op).unwrap();
+        assert_eq!(operators_op, operators());
+    })
 }
 
 /// Test inputs of PragmaConditional
@@ -492,37 +493,37 @@ fn test_pyo3_inputs_conditional() {
         create_circuit(),
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_pragma).unwrap();
 
-    let condition_register_op: &String = &String::extract(
-        operation
-            .call_method0(py, "condition_register")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    let condition_register_param: &String = &String::from("ro");
-    assert_eq!(condition_register_op, condition_register_param);
-
-    let condition_index_op: &usize = &usize::extract(
-        operation
-            .call_method0(py, "condition_index")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(condition_index_op, &1_usize);
+        let condition_register_op: &String = &String::extract(
+            operation
+                .call_method0(py, "condition_register")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        let condition_register_param: &String = &String::from("ro");
+        assert_eq!(condition_register_op, condition_register_param);
+
+        let condition_index_op: &usize = &usize::extract(
+            operation
+                .call_method0(py, "condition_index")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(condition_index_op, &1_usize);
 
-    let to_circuit = operation.call_method0(py, "circuit").unwrap();
-    let circuit_op = to_circuit.as_ref(py);
-    let circuit = new_circuit(py);
-    let paulix = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
-    circuit.call_method1("add", (paulix.clone(),)).unwrap();
-    let comparison_circuit =
-        bool::extract(circuit_op.call_method1("__eq__", (circuit,)).unwrap()).unwrap();
-    assert!(comparison_circuit);
+        let to_circuit = operation.call_method0(py, "circuit").unwrap();
+        let circuit_op = to_circuit.as_ref(py);
+        let circuit = new_circuit(py);
+        let paulix = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
+        circuit.call_method1("add", (paulix.clone(),)).unwrap();
+        let comparison_circuit =
+            bool::extract(circuit_op.call_method1("__eq__", (circuit,)).unwrap()).unwrap();
+        assert!(comparison_circuit);
+    })
 }
 
 /// Test involved_qubits function for Pragmas with None
@@ -531,13 +532,13 @@ fn test_pyo3_inputs_conditional() {
 #[test_case(Operation::from(PragmaGlobalPhase::new(CalculatorFloat::from(0.05))); "PragmaGlobalPhase")]
 fn test_pyo3_involved_qubits_none(input_definition: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
-    let involved_op: HashSet<usize> = HashSet::extract(to_involved.as_ref(py)).unwrap();
-    let involved_param: HashSet<usize> = HashSet::new();
-    assert_eq!(involved_op, involved_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
+        let involved_op: HashSet<usize> = HashSet::extract(to_involved.as_ref(py)).unwrap();
+        let involved_param: HashSet<usize> = HashSet::new();
+        assert_eq!(involved_op, involved_param);
+    })
 }
 
 /// Test involved_qubits function for Pragmas with All
@@ -546,14 +547,14 @@ fn test_pyo3_involved_qubits_none(input_definition: Operation) {
 #[test_case(Operation::from(PragmaRepeatGate::new(3)); "PragmaRepeatGate")]
 fn test_pyo3_involved_qubits_all(input_definition: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
-    let involved_op: HashSet<&str> = HashSet::extract(to_involved.as_ref(py)).unwrap();
-    let mut involved_param: HashSet<&str> = HashSet::new();
-    involved_param.insert("All");
-    assert_eq!(involved_op, involved_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
+        let involved_op: HashSet<&str> = HashSet::extract(to_involved.as_ref(py)).unwrap();
+        let mut involved_param: HashSet<&str> = HashSet::new();
+        involved_param.insert("All");
+        assert_eq!(involved_op, involved_param);
+    })
 }
 
 /// Test involved_qubits function for Pragmas with qubit 0
@@ -570,27 +571,27 @@ fn test_pyo3_involved_qubits_all(input_definition: Operation) {
 #[test_case(Operation::from(PragmaConditional::new(String::from("ro"), 1, create_circuit())); "PragmaConditional")]
 fn test_pyo3_involved_qubits_qubit(input_definition: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
-    let involved_op: HashSet<usize> = HashSet::extract(to_involved.as_ref(py)).unwrap();
-    let mut involved_param: HashSet<usize> = HashSet::new();
-    involved_param.insert(0);
-    assert_eq!(involved_op, involved_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
+        let involved_op: HashSet<usize> = HashSet::extract(to_involved.as_ref(py)).unwrap();
+        let mut involved_param: HashSet<usize> = HashSet::new();
+        involved_param.insert(0);
+        assert_eq!(involved_op, involved_param);
+    })
 }
 
 #[test_case(Operation::from(PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)); "PragmaOverrotation")]
 fn test_pyo3_involved_qubits_qubit_overrotation(input_definition: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_definition).unwrap();
-    let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
-    let involved_op: HashSet<usize> = HashSet::extract(to_involved.as_ref(py)).unwrap();
-    let mut involved_param: HashSet<usize> = HashSet::new();
-    involved_param.insert(0);
-    assert_eq!(involved_op, involved_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_definition).unwrap();
+        let to_involved = operation.call_method0(py, "involved_qubits").unwrap();
+        let involved_op: HashSet<usize> = HashSet::extract(to_involved.as_ref(py)).unwrap();
+        let mut involved_param: HashSet<usize> = HashSet::new();
+        involved_param.insert(0);
+        assert_eq!(involved_op, involved_param);
+    })
 }
 
 /// Test format and repr functions
@@ -630,30 +631,30 @@ fn test_pyo3_involved_qubits_qubit_overrotation(input_definition: Operation) {
             "PragmaConditional { condition_register: \"ro\", condition_index: 1, circuit: Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion } }"; "PragmaConditional")]
 fn test_pyo3_format_repr(input_measurement: Operation, format_repr: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-    let to_repr = operation.call_method0(py, "__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-    assert_eq!(format_op, format_repr);
-    assert_eq!(repr_op, format_repr);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+        let to_repr = operation.call_method0(py, "__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+        assert_eq!(format_op, format_repr);
+        assert_eq!(repr_op, format_repr);
+    })
 }
 
 #[test_case(Operation::from(PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)),
             "PragmaOverrotation { gate_hqslang: \"RotateX\", qubits: [0], amplitude: 0.03, variance: 0.001 }"; "PragmaOverrotation")]
 fn test_pyo3_format_repr_overrotation(input_measurement: Operation, format_repr: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-    let to_repr = operation.call_method0(py, "__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-    assert_eq!(format_op, format_repr);
-    assert_eq!(repr_op, format_repr);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+        let to_repr = operation.call_method0(py, "__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+        assert_eq!(format_op, format_repr);
+        assert_eq!(repr_op, format_repr);
+    })
 }
 
 /// Test copy and deepcopy functions
@@ -676,75 +677,75 @@ fn test_pyo3_format_repr_overrotation(input_measurement: Operation, format_repr:
 #[test_case(Operation::from(PragmaConditional::new(String::from("ro"), 1, create_circuit())); "PragmaConditional")]
 fn test_pyo3_copy_deepcopy(input_measurement: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let copy_op = operation.call_method0(py, "__copy__").unwrap();
-    let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
-    let copy_deepcopy_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        copy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-    let comparison_deepcopy = bool::extract(
-        deepcopy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let copy_op = operation.call_method0(py, "__copy__").unwrap();
+        let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
+        let copy_deepcopy_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            copy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+        let comparison_deepcopy = bool::extract(
+            deepcopy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 #[test]
 fn test_pyo3_copy_deepcopy_overrotation() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
-        "RotateX".to_string(),
-        vec![0],
-        0.03,
-        0.001,
-    )))
-    .unwrap();
-    let copy_op = operation.call_method0(py, "__copy__").unwrap();
-    let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
-
-    let extracted_copy: PragmaOverrotationWrapper =
-        PragmaOverrotationWrapper::extract(copy_op.as_ref(py)).unwrap();
-    assert_eq!(
-        extracted_copy.internal,
-        PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
-    );
-    let comparison_copy = bool::extract(
-        copy_op
-            .as_ref(py)
-            .call_method1("__eq__", (operation.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let extracted_copy: PragmaOverrotationWrapper =
-        PragmaOverrotationWrapper::extract(copy_op.as_ref(py)).unwrap();
-    assert_eq!(
-        extracted_copy.internal,
-        PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
-    );
-    let comparison_deepcopy = bool::extract(
-        deepcopy_op
-            .as_ref(py)
-            .call_method1("__eq__", (operation.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
+            "RotateX".to_string(),
+            vec![0],
+            0.03,
+            0.001,
+        )))
+        .unwrap();
+        let copy_op = operation.call_method0(py, "__copy__").unwrap();
+        let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
+
+        let extracted_copy: PragmaOverrotationWrapper =
+            PragmaOverrotationWrapper::extract(copy_op.as_ref(py)).unwrap();
+        assert_eq!(
+            extracted_copy.internal,
+            PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
+        );
+        let comparison_copy = bool::extract(
+            copy_op
+                .as_ref(py)
+                .call_method1("__eq__", (operation.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+
+        let extracted_copy: PragmaOverrotationWrapper =
+            PragmaOverrotationWrapper::extract(copy_op.as_ref(py)).unwrap();
+        assert_eq!(
+            extracted_copy.internal,
+            PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
+        );
+        let comparison_deepcopy = bool::extract(
+            deepcopy_op
+                .as_ref(py)
+                .call_method1("__eq__", (operation.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 /// Test tags function for simple Pragmas
@@ -756,13 +757,13 @@ fn test_pyo3_copy_deepcopy_overrotation() {
 #[test_case(Operation::from(PragmaGlobalPhase::new(CalculatorFloat::from(0.05))), "PragmaGlobalPhase"; "PragmaGlobalPhase")]
 fn test_pyo3_tags_simple(input_measurement: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &["Operation", "PragmaOperation", tag_name];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &["Operation", "PragmaOperation", tag_name];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test tags function for Pragmas that are also MultiQubitGates
@@ -772,85 +773,85 @@ fn test_pyo3_tags_simple(input_measurement: Operation, tag_name: &str) {
 #[test_case(Operation::from(PragmaStopDecompositionBlock::new(vec![0, 1])), "PragmaStopDecompositionBlock"; "PragmaStopDecompositionBlock")]
 fn test_pyo3_tags_multi(input_measurement: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &[
-        "Operation",
-        "MultiQubitOperation",
-        "PragmaOperation",
-        tag_name,
-    ];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &[
+            "Operation",
+            "MultiQubitOperation",
+            "PragmaOperation",
+            tag_name,
+        ];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 #[test_case(Operation::from(PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)), "PragmaOverrotation"; "PragmaOverrotation")]
 fn test_pyo3_tags_multi_overrotation(input_measurement: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &[
-        "Operation",
-        "MultiQubitOperation",
-        "PragmaOperation",
-        tag_name,
-    ];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &[
+            "Operation",
+            "MultiQubitOperation",
+            "PragmaOperation",
+            tag_name,
+        ];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test tags function for Pragmas that are also SingleQubitGates
 #[test_case(Operation::from(PragmaActiveReset::new(0)), "PragmaActiveReset"; "PragmaActiveReset")]
 fn test_pyo3_tags_single(input_measurement: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &[
-        "Operation",
-        "SingleQubitOperation",
-        "PragmaOperation",
-        tag_name,
-    ];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &[
+            "Operation",
+            "SingleQubitOperation",
+            "PragmaOperation",
+            tag_name,
+        ];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test tags function for Pragmas that are also SingleQubitGates
 #[test_case(Operation::from(PragmaConditional::new(String::from("ro"), 1, create_circuit())), "PragmaConditional"; "PragmaConditional")]
 fn test_pyo3_tags_conditional(input_measurement: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &["Operation", "PragmaOperation", tag_name];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &["Operation", "PragmaOperation", tag_name];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test tags function for PragmaGeneralNoise
 #[test_case(Operation::from(PragmaGeneralNoise::new(0, CalculatorFloat::from(0.005), operators())), "PragmaGeneralNoise"; "PragmaGeneralNoise")]
 fn test_pyo3_tags_general_noise(input_measurement: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &[
-        "Operation",
-        "SingleQubitOperation",
-        "PragmaOperation",
-        "PragmaNoiseOperation",
-        tag_name,
-    ];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &[
+            "Operation",
+            "SingleQubitOperation",
+            "PragmaOperation",
+            "PragmaNoiseOperation",
+            tag_name,
+        ];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test tags function for Noise Pragmas
@@ -860,20 +861,20 @@ fn test_pyo3_tags_general_noise(input_measurement: Operation, tag_name: &str) {
 #[test_case(Operation::from(PragmaRandomNoise::new(0, CalculatorFloat::from(0.005), CalculatorFloat::from(0.02), CalculatorFloat::from(0.01))), "PragmaRandomNoise"; "PragmaRandomNoise")]
 fn test_pyo3_tags_noise(input_measurement: Operation, tag_name: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let to_tag = operation.call_method0(py, "tags").unwrap();
-    let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
-    let tags_param: &[&str] = &[
-        "Operation",
-        "SingleQubitOperation",
-        "PragmaOperation",
-        "PragmaNoiseOperation",
-        "PragmaNoiseProbaOperation",
-        tag_name,
-    ];
-    assert_eq!(tags_op, tags_param);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let to_tag = operation.call_method0(py, "tags").unwrap();
+        let tags_op: &Vec<&str> = &Vec::extract(to_tag.as_ref(py)).unwrap();
+        let tags_param: &[&str] = &[
+            "Operation",
+            "SingleQubitOperation",
+            "PragmaOperation",
+            "PragmaNoiseOperation",
+            "PragmaNoiseProbaOperation",
+            tag_name,
+        ];
+        assert_eq!(tags_op, tags_param);
+    })
 }
 
 /// Test hqslang function
@@ -896,23 +897,23 @@ fn test_pyo3_tags_noise(input_measurement: Operation, tag_name: &str) {
 #[test_case(Operation::from(PragmaConditional::new(String::from("ro"), 1, create_circuit())), "PragmaConditional"; "PragmaConditional")]
 fn test_pyo3_hqslang(input_measurement: Operation, hqslang_param: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let hqslang_op: String =
-        String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
-    assert_eq!(hqslang_op, hqslang_param.to_string());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let hqslang_op: String =
+            String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
+        assert_eq!(hqslang_op, hqslang_param.to_string());
+    })
 }
 
 #[test_case(Operation::from(PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)), "PragmaOverrotation"; "PragmaOverrotation")]
 fn test_pyo3_hqslang_overrotation(input_measurement: Operation, hqslang_param: &str) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    let hqslang_op: String =
-        String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
-    assert_eq!(hqslang_op, hqslang_param.to_string());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        let hqslang_op: String =
+            String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
+        assert_eq!(hqslang_op, hqslang_param.to_string());
+    })
 }
 
 /// Test is_parametrized function
@@ -935,31 +936,31 @@ fn test_pyo3_hqslang_overrotation(input_measurement: Operation, hqslang_param: &
 #[test_case(Operation::from(PragmaConditional::new(String::from("ro"), 1, create_circuit())); "PragmaConditional")]
 fn test_pyo3_is_parametrized(input_measurement: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    assert!(!bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        assert!(!bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 #[test_case(Operation::from(PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)); "PragmaOverrotation")]
 fn test_pyo3_is_parametrized_overrotation(input_measurement: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_measurement).unwrap();
-    assert!(!bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_measurement).unwrap();
+        assert!(!bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 /// Test substitute_parameters function
@@ -1016,60 +1017,60 @@ fn test_pyo3_is_parametrized_overrotation(input_measurement: Operation) {
             "PragmaConditional")]
 fn test_pyo3_substitute_parameters(first_op: Operation, second_op: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(first_op).unwrap();
-    let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
-    substitution_dict.insert("test", 1.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict,))
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(first_op).unwrap();
+        let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
+        substitution_dict.insert("test", 1.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict,))
+            .unwrap();
+        let substitute_param = convert_operation_to_pyobject(second_op).unwrap();
+
+        let comparison = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (substitute_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let substitute_param = convert_operation_to_pyobject(second_op).unwrap();
-
-    let comparison = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (substitute_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        assert!(comparison);
+    })
 }
 
 #[test]
 fn test_pyo3_substitute_parameters_overrotation() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
-        "RotateX".to_string(),
-        vec![0],
-        0.03,
-        0.001,
-    )))
-    .unwrap();
-
-    let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
-    substitution_dict.insert("test", 1.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict,))
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
+            "RotateX".to_string(),
+            vec![0],
+            0.03,
+            0.001,
+        )))
         .unwrap();
 
-    let extracted: PragmaOverrotationWrapper =
-        PragmaOverrotationWrapper::extract(substitute_op.as_ref(py)).unwrap();
-    assert_eq!(
-        extracted.internal,
-        PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
-    );
-
-    let comparison = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (operation.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
+        substitution_dict.insert("test", 1.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict,))
+            .unwrap();
+
+        let extracted: PragmaOverrotationWrapper =
+            PragmaOverrotationWrapper::extract(substitute_op.as_ref(py)).unwrap();
+        assert_eq!(
+            extracted.internal,
+            PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
+        );
+
+        let comparison = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (operation.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 /// Test substitute_parameters() causing an error `None`
@@ -1093,13 +1094,13 @@ fn test_pyo3_substitute_parameters_overrotation() {
             "PragmaGeneralNoise")]
 fn test_pyo3_substitute_params_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let substitution_dict: HashMap<&str, f64> = HashMap::new();
-    let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let substitution_dict: HashMap<&str, f64> = HashMap::new();
+        let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test substitute_parameters() causing an error `not-a-real-number`
@@ -1107,14 +1108,14 @@ fn test_pyo3_substitute_params_error(input_operation: Operation) {
 #[test_case(Operation::from(PragmaConditional::new(String::from("ro"), 1, create_circuit())); "PragmaConditional")]
 fn test_pyo3_substituteparameters_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let mut substitution_dict: HashMap<&str, &str> = HashMap::new();
-    substitution_dict.insert("ro", "test");
-    let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let mut substitution_dict: HashMap<&str, &str> = HashMap::new();
+        substitution_dict.insert("ro", "test");
+        let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test remap_qubits function
@@ -1171,68 +1172,65 @@ fn test_pyo3_substituteparameters_error(input_operation: Operation) {
             "PragmaConditional")]
 fn test_pyo3_remap_qubits(first_op: Operation, second_op: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(first_op).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(first_op).unwrap();
 
-    let remapped_op = operation
-        .call_method1(py, "remap_qubits", (qubit_remapping(),))
-        .unwrap();
-    let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
+        let remapped_op = operation
+            .call_method1(py, "remap_qubits", (qubit_remapping(),))
+            .unwrap();
+        let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
 
-    let comparison = bool::extract(
-        remapped_op
-            .call_method1(py, "__eq__", (comparison_op,))
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert!(comparison);
+        let comparison = bool::extract(
+            remapped_op
+                .call_method1(py, "__eq__", (comparison_op,))
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 #[test]
 fn test_pyo3_remap_qubits_overrotation() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
-        "RotateX".to_string(),
-        vec![0],
-        0.03,
-        0.001,
-    )))
-    .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
+            "RotateX".to_string(),
+            vec![0],
+            0.03,
+            0.001,
+        )))
+        .unwrap();
 
-    let remapped_op = operation
-        .call_method1(py, "remap_qubits", (qubit_remapping(),))
+        let remapped_op = operation
+            .call_method1(py, "remap_qubits", (qubit_remapping(),))
+            .unwrap();
+        let extracted: PragmaOverrotationWrapper =
+            PragmaOverrotationWrapper::extract(remapped_op.as_ref(py)).unwrap();
+        assert_eq!(
+            extracted.internal,
+            PragmaOverrotation::new("RotateX".to_string(), vec![2], 0.03, 0.001)
+        );
+
+        let operation_two = convert_operation_to_pyobject(Operation::from(
+            PragmaOverrotation::new("RotateX".to_string(), vec![2], 0.03, 0.001),
+        ))
         .unwrap();
-    let extracted: PragmaOverrotationWrapper =
-        PragmaOverrotationWrapper::extract(remapped_op.as_ref(py)).unwrap();
-    assert_eq!(
-        extracted.internal,
-        PragmaOverrotation::new("RotateX".to_string(), vec![2], 0.03, 0.001)
-    );
-
-    let operation_two = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
-        "RotateX".to_string(),
-        vec![2],
-        0.03,
-        0.001,
-    )))
-    .unwrap();
-    let comparison = bool::extract(
-        remapped_op
-            .as_ref(py)
-            .call_method1("__eq__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        let comparison = bool::extract(
+            remapped_op
+                .as_ref(py)
+                .call_method1("__eq__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
 
-    let qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+        let qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test superoperator of PragmaDamping
@@ -1242,26 +1240,26 @@ fn test_pyo3_noise_superoperator_damping() {
         PragmaDamping::new(0, CalculatorFloat::from(0.005), CalculatorFloat::from(0.02));
     let noise_pragma = Operation::from(pragma_op.clone());
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
-
-    let superop_prob: f64 = f64::try_from(pragma_op.probability()).unwrap();
-    let superop_sqrt: f64 = (1.0 - superop_prob).sqrt();
-    let superop_param: Array2<f64> = arr2(&[
-        [1.0, 0.0, 0.0, superop_prob],
-        [0.0, superop_sqrt, 0.0, 0.0],
-        [0.0, 0.0, superop_sqrt, 0.0],
-        [0.0, 0.0, 0.0, 1.0 - superop_prob],
-    ]);
-
-    let to_superop_op = operation.call_method0(py, "superoperator").unwrap();
-    let superop_op = to_superop_op
-        .cast_as::<PyArray2<f64>>(py)
-        .unwrap()
-        .to_owned_array();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
+
+        let superop_prob: f64 = f64::try_from(pragma_op.probability()).unwrap();
+        let superop_sqrt: f64 = (1.0 - superop_prob).sqrt();
+        let superop_param: Array2<f64> = arr2(&[
+            [1.0, 0.0, 0.0, superop_prob],
+            [0.0, superop_sqrt, 0.0, 0.0],
+            [0.0, 0.0, superop_sqrt, 0.0],
+            [0.0, 0.0, 0.0, 1.0 - superop_prob],
+        ]);
+
+        let to_superop_op = operation.call_method0(py, "superoperator").unwrap();
+        let superop_op = to_superop_op
+            .cast_as::<PyArray2<f64>>(py)
+            .unwrap()
+            .to_owned_array();
 
-    assert_eq!(superop_op, superop_param);
+        assert_eq!(superop_op, superop_param);
+    })
 }
 
 /// Test superoperator of PragmaDamping
@@ -1273,29 +1271,29 @@ fn test_pyo3_noise_superoperator_depolarising() {
         CalculatorFloat::from(0.02),
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
-
-    let superop_pre_exp: f64 = -1.0 * 0.005 * 0.02;
-    let superop_prob: f64 = 0.75 * (1.0 - superop_pre_exp.exp());
-    let superop_proba1: f64 = 1.0 - (2.0 / 3.0) * superop_prob.clone();
-    let superop_proba2: f64 = 1.0 - (4.0 / 3.0) * superop_prob.clone();
-    let superop_proba3: f64 = (2.0 / 3.0) * superop_prob.clone();
-    let superop_param: Array2<f64> = arr2(&[
-        [superop_proba1, 0.0, 0.0, superop_proba3],
-        [0.0, superop_proba2, 0.0, 0.0],
-        [0.0, 0.0, superop_proba2, 0.0],
-        [superop_proba3, 0.0, 0.0, superop_proba1],
-    ]);
-
-    let to_superop_op = operation.call_method0(py, "superoperator").unwrap();
-    let superop_op = to_superop_op
-        .cast_as::<PyArray2<f64>>(py)
-        .unwrap()
-        .to_owned_array();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
+
+        let superop_pre_exp: f64 = -1.0 * 0.005 * 0.02;
+        let superop_prob: f64 = 0.75 * (1.0 - superop_pre_exp.exp());
+        let superop_proba1: f64 = 1.0 - (2.0 / 3.0) * superop_prob.clone();
+        let superop_proba2: f64 = 1.0 - (4.0 / 3.0) * superop_prob.clone();
+        let superop_proba3: f64 = (2.0 / 3.0) * superop_prob.clone();
+        let superop_param: Array2<f64> = arr2(&[
+            [superop_proba1, 0.0, 0.0, superop_proba3],
+            [0.0, superop_proba2, 0.0, 0.0],
+            [0.0, 0.0, superop_proba2, 0.0],
+            [superop_proba3, 0.0, 0.0, superop_proba1],
+        ]);
+
+        let to_superop_op = operation.call_method0(py, "superoperator").unwrap();
+        let superop_op = to_superop_op
+            .cast_as::<PyArray2<f64>>(py)
+            .unwrap()
+            .to_owned_array();
 
-    assert_eq!(superop_op, superop_param);
+        assert_eq!(superop_op, superop_param);
+    })
 }
 
 /// Test superoperator of PragmaDamping
@@ -1307,27 +1305,27 @@ fn test_pyo3_noise_superoperator_dephasing() {
         CalculatorFloat::from(0.02),
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
-
-    let superop_pre_exp: f64 = -2.0 * 0.005 * 0.02;
-    let superop_prob: f64 = 0.5 * (1.0 - superop_pre_exp.exp());
-    let superop_proba1: f64 = 1.0 - 2.0 * superop_prob;
-    let superop_param: Array2<f64> = arr2(&[
-        [1.0, 0.0, 0.0, 0.0],
-        [0.0, superop_proba1, 0.0, 0.0],
-        [0.0, 0.0, superop_proba1, 0.0],
-        [0.0, 0.0, 0.0, 1.0],
-    ]);
-
-    let to_superop_op = operation.call_method0(py, "superoperator").unwrap();
-    let superop_op = to_superop_op
-        .cast_as::<PyArray2<f64>>(py)
-        .unwrap()
-        .to_owned_array();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
+
+        let superop_pre_exp: f64 = -2.0 * 0.005 * 0.02;
+        let superop_prob: f64 = 0.5 * (1.0 - superop_pre_exp.exp());
+        let superop_proba1: f64 = 1.0 - 2.0 * superop_prob;
+        let superop_param: Array2<f64> = arr2(&[
+            [1.0, 0.0, 0.0, 0.0],
+            [0.0, superop_proba1, 0.0, 0.0],
+            [0.0, 0.0, superop_proba1, 0.0],
+            [0.0, 0.0, 0.0, 1.0],
+        ]);
+
+        let to_superop_op = operation.call_method0(py, "superoperator").unwrap();
+        let superop_op = to_superop_op
+            .cast_as::<PyArray2<f64>>(py)
+            .unwrap()
+            .to_owned_array();
 
-    assert_eq!(superop_op, superop_param);
+        assert_eq!(superop_op, superop_param);
+    })
 }
 
 /// Test superoperator of PragmaDamping
@@ -1340,27 +1338,27 @@ fn test_pyo3_noise_superoperator_randomnoise() {
         CalculatorFloat::from(0.01),
     ));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
-
-    let superop_pre_exp: f64 = -2.0 * 0.005 * 0.01;
-    let superop_prob: f64 = 0.5 * (1.0 - superop_pre_exp.exp());
-    let superop_proba1: f64 = 1.0 - 2.0 * superop_prob;
-    let superop_param: Array2<f64> = arr2(&[
-        [1.0, 0.0, 0.0, 0.0],
-        [0.0, superop_proba1, 0.0, 0.0],
-        [0.0, 0.0, superop_proba1, 0.0],
-        [0.0, 0.0, 0.0, 1.0],
-    ]);
-
-    let to_superop_op = operation.call_method0(py, "superoperator").unwrap();
-    let superop_op = to_superop_op
-        .cast_as::<PyArray2<f64>>(py)
-        .unwrap()
-        .to_owned_array();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
+
+        let superop_pre_exp: f64 = -2.0 * 0.005 * 0.01;
+        let superop_prob: f64 = 0.5 * (1.0 - superop_pre_exp.exp());
+        let superop_proba1: f64 = 1.0 - 2.0 * superop_prob;
+        let superop_param: Array2<f64> = arr2(&[
+            [1.0, 0.0, 0.0, 0.0],
+            [0.0, superop_proba1, 0.0, 0.0],
+            [0.0, 0.0, superop_proba1, 0.0],
+            [0.0, 0.0, 0.0, 1.0],
+        ]);
+
+        let to_superop_op = operation.call_method0(py, "superoperator").unwrap();
+        let superop_op = to_superop_op
+            .cast_as::<PyArray2<f64>>(py)
+            .unwrap()
+            .to_owned_array();
 
-    assert_eq!(superop_op, superop_param);
+        assert_eq!(superop_op, superop_param);
+    })
 }
 
 /// Test probability function of Noise Pragmas
@@ -1370,21 +1368,21 @@ fn test_pyo3_noise_superoperator_randomnoise() {
 #[test_case(Operation::from(PragmaRandomNoise::new(0, CalculatorFloat::from(0.005), CalculatorFloat::from(0.02), CalculatorFloat::from(0.01))), 0.000125; "PragmaRandomNoise")]
 fn test_pyo3_noise_proba(noise_pragma: Operation, proba: f64) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(noise_pragma).unwrap();
 
-    let gate_time_op: &f64 = &f64::extract(
-        operation
-            .call_method0(py, "probability")
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert_eq!(
-        CalculatorFloat::from(gate_time_op),
-        CalculatorFloat::from(proba),
-    );
+        let gate_time_op: &f64 = &f64::extract(
+            operation
+                .call_method0(py, "probability")
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert_eq!(
+            CalculatorFloat::from(gate_time_op),
+            CalculatorFloat::from(proba),
+        );
+    })
 }
 
 /// Test powercf function of Noise Pragmas
@@ -1402,22 +1400,22 @@ fn test_pyo3_noise_proba(noise_pragma: Operation, proba: f64) {
             "PragmaRandomNoise")]
 fn test_pyo3_noise_powercf(first_op: Operation, second_op: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(first_op).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(first_op).unwrap();
 
-    let power = convert_cf_to_pyobject(py, CalculatorFloat::from(1.5));
-    let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
+        let power = convert_cf_to_pyobject(py, CalculatorFloat::from(1.5));
+        let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
 
-    let remapped_op = operation.call_method1(py, "powercf", (power,)).unwrap();
-    let comparison = bool::extract(
-        remapped_op
-            .call_method1(py, "__eq__", (comparison_op,))
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert!(comparison);
+        let remapped_op = operation.call_method1(py, "powercf", (power,)).unwrap();
+        let comparison = bool::extract(
+            remapped_op
+                .call_method1(py, "__eq__", (comparison_op,))
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 /// Test the __richcmp__ function
@@ -1474,1029 +1472,1014 @@ fn test_pyo3_noise_powercf(first_op: Operation, second_op: Operation) {
             "PragmaConditional")]
 fn test_pyo3_richcmp(definition_1: Operation, definition_2: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
-    let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
+        let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
 
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__eq__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(!comparison);
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__ne__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__eq__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(!comparison);
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__ne__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
 
-    let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
+        assert!(comparison.is_err());
 
-    let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
+        assert!(comparison.is_err());
+    })
 }
 
 #[test]
 fn test_pyo3_richcmp_overrotation() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_one = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
-        "RotateX".to_string(),
-        vec![0],
-        0.03,
-        0.001,
-    )))
-    .unwrap();
-    let operation_two = convert_operation_to_pyobject(Operation::from(PragmaOverrotation::new(
-        "RotateX".to_string(),
-        vec![1],
-        0.03,
-        0.001,
-    )))
-    .unwrap();
-
-    let extracted_one: PragmaOverrotationWrapper =
-        PragmaOverrotationWrapper::extract(operation_one.as_ref(py)).unwrap();
-    assert_eq!(
-        extracted_one.internal,
-        PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
-    );
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__ne__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let operation_one = convert_operation_to_pyobject(Operation::from(
+            PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001),
+        ))
+        .unwrap();
+        let operation_two = convert_operation_to_pyobject(Operation::from(
+            PragmaOverrotation::new("RotateX".to_string(), vec![1], 0.03, 0.001),
+        ))
+        .unwrap();
+
+        let extracted_one: PragmaOverrotationWrapper =
+            PragmaOverrotationWrapper::extract(operation_one.as_ref(py)).unwrap();
+        assert_eq!(
+            extracted_one.internal,
+            PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
+        );
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__ne__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
 
-    let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
+        assert!(comparison.is_err());
 
-    let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
+        assert!(comparison.is_err());
+    })
 }
 
 /// Test PragmaSetNumberOfMeasurements new() function
 #[test]
 fn test_pyo3_new_set_number_of_measurements() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaSetNumberOfMeasurementsWrapper>();
-    let new_op = operation
-        .call1((1, "ro".to_string()))
-        .unwrap()
-        .cast_as::<PyCell<PragmaSetNumberOfMeasurementsWrapper>>()
-        .unwrap();
-
-    let input_definition =
-        Operation::from(PragmaSetNumberOfMeasurements::new(1, String::from("ro")));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaSetNumberOfMeasurementsWrapper>();
+        let new_op = operation
+            .call1((1, "ro".to_string()))
+            .unwrap()
+            .cast_as::<PyCell<PragmaSetNumberOfMeasurementsWrapper>>()
+            .unwrap();
 
-    let pragma_wrapper = new_op
-        .extract::<PragmaSetNumberOfMeasurementsWrapper>()
-        .unwrap();
-    let new_op_diff = operation
-        .call1((2, "ro".to_string()))
-        .unwrap()
-        .cast_as::<PyCell<PragmaSetNumberOfMeasurementsWrapper>>()
-        .unwrap();
-    let pragma_wrapper_diff = new_op_diff
-        .extract::<PragmaSetNumberOfMeasurementsWrapper>()
+        let input_definition =
+            Operation::from(PragmaSetNumberOfMeasurements::new(1, String::from("ro")));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaSetNumberOfMeasurementsWrapper { internal: PragmaSetNumberOfMeasurements { number_measurements: 1, readout: \"ro\" } }"
-    );
+        let pragma_wrapper = new_op
+            .extract::<PragmaSetNumberOfMeasurementsWrapper>()
+            .unwrap();
+        let new_op_diff = operation
+            .call1((2, "ro".to_string()))
+            .unwrap()
+            .cast_as::<PyCell<PragmaSetNumberOfMeasurementsWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff
+            .extract::<PragmaSetNumberOfMeasurementsWrapper>()
+            .unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaSetNumberOfMeasurementsWrapper { internal: PragmaSetNumberOfMeasurements { number_measurements: 1, readout: \"ro\" } }"
+        );
+    })
 }
 
 /// Test PragmaSetStateVector new() function
 #[test]
 fn test_pyo3_new_set_statevector() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaSetStateVectorWrapper>();
-    let to_get_statevec_0 = Operation::from(PragmaSetStateVector::new(statevector()));
-    let convert_to_get_statevec_0 = convert_operation_to_pyobject(to_get_statevec_0)
-        .unwrap()
-        .clone();
-    let statevector_op_0 = convert_to_get_statevec_0
-        .call_method0(py, "statevector")
-        .unwrap();
-    let new_op = operation
-        .call1((statevector_op_0,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaSetStateVectorWrapper>>()
-        .unwrap();
-
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (convert_to_get_statevec_0.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let to_get_statevec_1 = Operation::from(PragmaSetStateVector::new(statevector() + 1.0));
-    let convert_to_get_statevec_1 = convert_operation_to_pyobject(to_get_statevec_1)
-        .unwrap()
-        .clone();
-    let statevector_op_1 = convert_to_get_statevec_1
-        .call_method0(py, "statevector")
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaSetStateVectorWrapper>();
+        let to_get_statevec_0 = Operation::from(PragmaSetStateVector::new(statevector()));
+        let convert_to_get_statevec_0 = convert_operation_to_pyobject(to_get_statevec_0)
+            .unwrap()
+            .clone();
+        let statevector_op_0 = convert_to_get_statevec_0
+            .call_method0(py, "statevector")
+            .unwrap();
+        let new_op = operation
+            .call1((statevector_op_0,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaSetStateVectorWrapper>>()
+            .unwrap();
+
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (convert_to_get_statevec_0.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison_copy);
 
-    let pragma_wrapper = new_op.extract::<PragmaSetStateVectorWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((statevector_op_1,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaSetStateVectorWrapper>>()
-        .unwrap();
-    let pragma_wrapper_diff = new_op_diff
-        .extract::<PragmaSetStateVectorWrapper>()
-        .unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        let to_get_statevec_1 = Operation::from(PragmaSetStateVector::new(statevector() + 1.0));
+        let convert_to_get_statevec_1 = convert_operation_to_pyobject(to_get_statevec_1)
+            .unwrap()
+            .clone();
+        let statevector_op_1 = convert_to_get_statevec_1
+            .call_method0(py, "statevector")
+            .unwrap();
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaSetStateVectorWrapper { internal: PragmaSetStateVector { statevector: [Complex { re: 1.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }], shape=[4], strides=[1], layout=CFcf (0xf), const ndim=1 } }"
-    );
+        let pragma_wrapper = new_op.extract::<PragmaSetStateVectorWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((statevector_op_1,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaSetStateVectorWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff
+            .extract::<PragmaSetStateVectorWrapper>()
+            .unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaSetStateVectorWrapper { internal: PragmaSetStateVector { statevector: [Complex { re: 1.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }], shape=[4], strides=[1], layout=CFcf (0xf), const ndim=1 } }"
+        );
+    })
 }
 
 /// Test PragmaSetDensityMatrix new() function
 #[test]
 fn test_pyo3_new_set_densitymatrix() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaSetDensityMatrixWrapper>();
-    let to_get_densmat_0 = Operation::from(PragmaSetDensityMatrix::new(densitymatrix()));
-    let convert_to_get_densmat_0 = convert_operation_to_pyobject(to_get_densmat_0)
-        .unwrap()
-        .clone();
-    let densmat_op_0 = convert_to_get_densmat_0
-        .call_method0(py, "density_matrix")
-        .unwrap();
-    let new_op = operation
-        .call1((densmat_op_0,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaSetDensityMatrixWrapper>>()
-        .unwrap();
-
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (convert_to_get_densmat_0.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    let to_get_densmat_1 = Operation::from(PragmaSetDensityMatrix::new(densitymatrix() + 1.0));
-    let convert_to_get_densmat_1 = convert_operation_to_pyobject(to_get_densmat_1)
-        .unwrap()
-        .clone();
-    let densmat_op_1 = convert_to_get_densmat_1
-        .call_method0(py, "density_matrix")
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaSetDensityMatrixWrapper>();
+        let to_get_densmat_0 = Operation::from(PragmaSetDensityMatrix::new(densitymatrix()));
+        let convert_to_get_densmat_0 = convert_operation_to_pyobject(to_get_densmat_0)
+            .unwrap()
+            .clone();
+        let densmat_op_0 = convert_to_get_densmat_0
+            .call_method0(py, "density_matrix")
+            .unwrap();
+        let new_op = operation
+            .call1((densmat_op_0,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaSetDensityMatrixWrapper>>()
+            .unwrap();
+
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (convert_to_get_densmat_0.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison_copy);
 
-    let pragma_wrapper = new_op.extract::<PragmaSetDensityMatrixWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((densmat_op_1,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaSetDensityMatrixWrapper>>()
-        .unwrap();
-    let pragma_wrapper_diff = new_op_diff
-        .extract::<PragmaSetDensityMatrixWrapper>()
-        .unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        let to_get_densmat_1 = Operation::from(PragmaSetDensityMatrix::new(densitymatrix() + 1.0));
+        let convert_to_get_densmat_1 = convert_operation_to_pyobject(to_get_densmat_1)
+            .unwrap()
+            .clone();
+        let densmat_op_1 = convert_to_get_densmat_1
+            .call_method0(py, "density_matrix")
+            .unwrap();
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaSetDensityMatrixWrapper { internal: PragmaSetDensityMatrix { density_matrix: [[Complex { re: 1.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }],\n [Complex { re: 0.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }]], shape=[2, 2], strides=[2, 1], layout=Cc (0x5), const ndim=2 } }"
-    );
+        let pragma_wrapper = new_op.extract::<PragmaSetDensityMatrixWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((densmat_op_1,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaSetDensityMatrixWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff
+            .extract::<PragmaSetDensityMatrixWrapper>()
+            .unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaSetDensityMatrixWrapper { internal: PragmaSetDensityMatrix { density_matrix: [[Complex { re: 1.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }],\n [Complex { re: 0.0, im: 0.0 }, Complex { re: 0.0, im: 0.0 }]], shape=[2, 2], strides=[2, 1], layout=Cc (0x5), const ndim=2 } }"
+        );
+    })
 }
 
 /// Test PragmaRepeatGate new() function
 #[test]
 fn test_pyo3_new_repeated_gate() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaRepeatGateWrapper>();
-    let new_op = operation
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaRepeatGateWrapper>>()
-        .unwrap();
-
-    let input_definition = Operation::from(PragmaRepeatGate::new(2));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaRepeatGateWrapper>();
+        let new_op = operation
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaRepeatGateWrapper>>()
+            .unwrap();
 
-    let pragma_wrapper = new_op.extract::<PragmaRepeatGateWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((3,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaRepeatGateWrapper>>()
+        let input_definition = Operation::from(PragmaRepeatGate::new(2));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaRepeatGateWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
+
+        let pragma_wrapper = new_op.extract::<PragmaRepeatGateWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((3,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaRepeatGateWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaRepeatGateWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaRepeatGateWrapper { internal: PragmaRepeatGate { repetition_coefficient: 2 } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaRepeatGateWrapper { internal: PragmaRepeatGate { repetition_coefficient: 2 } }"
+        );
+    })
 }
 
 /// Test PragmaOverrotation new() function
 #[test]
 fn test_pyo3_new_overrotation() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaOverrotationWrapper>();
-    let new_op = operation
-        .call1(("RotateX", vec![0], 0.03, 0.001))
-        .unwrap()
-        .cast_as::<PyCell<PragmaOverrotationWrapper>>()
-        .unwrap();
-    let input_definition = Operation::from(PragmaOverrotation::new(
-        "RotateX".to_string(),
-        vec![0],
-        0.03,
-        0.001,
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let extracted: PragmaOverrotationWrapper =
-        PragmaOverrotationWrapper::extract(new_op.as_ref()).unwrap();
-    assert_eq!(
-        extracted.internal,
-        PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
-    );
-    let comparison = bool::extract(
-        new_op
-            .as_ref()
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaOverrotationWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("RotateX", vec![1], 0.03, 0.001))
-        .unwrap()
-        .cast_as::<PyCell<PragmaOverrotationWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaOverrotationWrapper>();
+        let new_op = operation
+            .call1(("RotateX", vec![0], 0.03, 0.001))
+            .unwrap()
+            .cast_as::<PyCell<PragmaOverrotationWrapper>>()
+            .unwrap();
+        let input_definition = Operation::from(PragmaOverrotation::new(
+            "RotateX".to_string(),
+            vec![0],
+            0.03,
+            0.001,
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let extracted: PragmaOverrotationWrapper =
+            PragmaOverrotationWrapper::extract(new_op.as_ref()).unwrap();
+        assert_eq!(
+            extracted.internal,
+            PragmaOverrotation::new("RotateX".to_string(), vec![0], 0.03, 0.001)
+        );
+        let comparison = bool::extract(
+            new_op
+                .as_ref()
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaOverrotationWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaOverrotationWrapper { internal: PragmaOverrotation { gate_hqslang: \"RotateX\", qubits: [0], amplitude: 0.03, variance: 0.001 } }"
-    );
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaOverrotationWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("RotateX", vec![1], 0.03, 0.001))
+            .unwrap()
+            .cast_as::<PyCell<PragmaOverrotationWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaOverrotationWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaOverrotationWrapper { internal: PragmaOverrotation { gate_hqslang: \"RotateX\", qubits: [0], amplitude: 0.03, variance: 0.001 } }"
+        );
+    })
 }
 
 /// Test PragmaBoostNoise new() function
 #[test]
 fn test_pyo3_new_boost_noise() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaBoostNoiseWrapper>();
-    let new_op = operation
-        .call1((0.003,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaBoostNoiseWrapper>>()
-        .unwrap();
-    let input_definition = Operation::from(PragmaBoostNoise::new(CalculatorFloat::from(0.003)));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((vec!["fails"],));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaBoostNoiseWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((0.001,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaBoostNoiseWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaBoostNoiseWrapper>();
+        let new_op = operation
+            .call1((0.003,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaBoostNoiseWrapper>>()
+            .unwrap();
+        let input_definition = Operation::from(PragmaBoostNoise::new(CalculatorFloat::from(0.003)));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaBoostNoiseWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
+
+        // Error initialisation
+        let result = operation.call1((vec!["fails"],));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaBoostNoiseWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((0.001,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaBoostNoiseWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaBoostNoiseWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaBoostNoiseWrapper { internal: PragmaBoostNoise { noise_coefficient: Float(0.003) } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaBoostNoiseWrapper { internal: PragmaBoostNoise { noise_coefficient: Float(0.003) } }"
+        );
+    })
 }
 
 /// Test PragmaStopParallelBlock new() function
 #[test]
 fn test_pyo3_new_stop() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaStopParallelBlockWrapper>();
-    let new_op = operation
-        .call1((vec![0], 0.0000001))
-        .unwrap()
-        .cast_as::<PyCell<PragmaStopParallelBlockWrapper>>()
-        .unwrap();
-    let input_definition = Operation::from(PragmaStopParallelBlock::new(
-        vec![0],
-        CalculatorFloat::from(0.0000001),
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((vec![0], vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaStopParallelBlockWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((vec![1], 0.0000001))
-        .unwrap()
-        .cast_as::<PyCell<PragmaStopParallelBlockWrapper>>()
-        .unwrap();
-    let pragma_wrapper_diff = new_op_diff
-        .extract::<PragmaStopParallelBlockWrapper>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaStopParallelBlockWrapper>();
+        let new_op = operation
+            .call1((vec![0], 0.0000001))
+            .unwrap()
+            .cast_as::<PyCell<PragmaStopParallelBlockWrapper>>()
+            .unwrap();
+        let input_definition = Operation::from(PragmaStopParallelBlock::new(
+            vec![0],
+            CalculatorFloat::from(0.0000001),
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
 
-    let string_comparison = (
-        format!("{:?}", pragma_wrapper) == 
-        "PragmaStopParallelBlockWrapper { internal: PragmaStopParallelBlock { qubits: [0], execution_time: Float(0.0000001) } }"
-    ) || (
-        format!("{:?}", pragma_wrapper) == 
-        "PragmaStopParallelBlockWrapper { internal: PragmaStopParallelBlock { qubits: [0], execution_time: Float(1e-7) } }"
-    );
+        // Error initialisation
+        let result = operation.call1((vec![0], vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
 
-    assert!(string_comparison)
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaStopParallelBlockWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((vec![1], 0.0000001))
+            .unwrap()
+            .cast_as::<PyCell<PragmaStopParallelBlockWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff
+            .extract::<PragmaStopParallelBlockWrapper>()
+            .unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        let string_comparison = (
+            format!("{:?}", pragma_wrapper) == 
+            "PragmaStopParallelBlockWrapper { internal: PragmaStopParallelBlock { qubits: [0], execution_time: Float(0.0000001) } }"
+        ) || (
+            format!("{:?}", pragma_wrapper) == 
+            "PragmaStopParallelBlockWrapper { internal: PragmaStopParallelBlock { qubits: [0], execution_time: Float(1e-7) } }"
+        );
+
+        assert!(string_comparison)
+    })
 }
 
 /// Test PragmaGlobalPhase new() function
 #[test]
 fn test_pyo3_new_global_phase() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaGlobalPhaseWrapper>();
-    let new_op = operation
-        .call1((0.003,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGlobalPhaseWrapper>>()
-        .unwrap();
-    let input_definition = Operation::from(PragmaGlobalPhase::new(CalculatorFloat::from(0.003)));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((vec!["fails"],));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaGlobalPhaseWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((0.001,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGlobalPhaseWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaGlobalPhaseWrapper>();
+        let new_op = operation
+            .call1((0.003,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGlobalPhaseWrapper>>()
+            .unwrap();
+        let input_definition =
+            Operation::from(PragmaGlobalPhase::new(CalculatorFloat::from(0.003)));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaGlobalPhaseWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
+
+        // Error initialisation
+        let result = operation.call1((vec!["fails"],));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaGlobalPhaseWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((0.001,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGlobalPhaseWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaGlobalPhaseWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaGlobalPhaseWrapper { internal: PragmaGlobalPhase { phase: Float(0.003) } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaGlobalPhaseWrapper { internal: PragmaGlobalPhase { phase: Float(0.003) } }"
+        );
+    })
 }
 
 /// Test PragmaSleep new() function
 #[test]
 fn test_pyo3_new_sleep() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaSleepWrapper>();
-    let new_op = operation
-        .call1((vec![0], 0.0000001))
-        .unwrap()
-        .cast_as::<PyCell<PragmaSleepWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaSleepWrapper>();
+        let new_op = operation
+            .call1((vec![0], 0.0000001))
+            .unwrap()
+            .cast_as::<PyCell<PragmaSleepWrapper>>()
+            .unwrap();
 
-    let input_definition =
-        Operation::from(PragmaSleep::new(vec![0], CalculatorFloat::from(0.0000001)));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((vec![0], vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaSleepWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((vec![1], 0.0000001))
-        .unwrap()
-        .cast_as::<PyCell<PragmaSleepWrapper>>()
+        let input_definition =
+            Operation::from(PragmaSleep::new(vec![0], CalculatorFloat::from(0.0000001)));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaSleepWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
 
-    let string_comparison = (
-        format!("{:?}", pragma_wrapper) == 
-        "PragmaSleepWrapper { internal: PragmaSleep { qubits: [0], sleep_time: Float(0.0000001) } }"
-    ) || (
-        format!("{:?}", pragma_wrapper) == 
-        "PragmaSleepWrapper { internal: PragmaSleep { qubits: [0], sleep_time: Float(1e-7) } }"
-    );
+        // Error initialisation
+        let result = operation.call1((vec![0], vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
 
-    assert!(string_comparison)
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaSleepWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((vec![1], 0.0000001))
+            .unwrap()
+            .cast_as::<PyCell<PragmaSleepWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaSleepWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        let string_comparison = (
+            format!("{:?}", pragma_wrapper) == 
+            "PragmaSleepWrapper { internal: PragmaSleep { qubits: [0], sleep_time: Float(0.0000001) } }"
+        ) || (
+            format!("{:?}", pragma_wrapper) == 
+            "PragmaSleepWrapper { internal: PragmaSleep { qubits: [0], sleep_time: Float(1e-7) } }"
+        );
+
+        assert!(string_comparison)
+    })
 }
 
 /// Test PragmaActiveReset new() function
 #[test]
 fn test_pyo3_new_active_reset() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaActiveResetWrapper>();
-    let new_op = operation
-        .call1((0,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaActiveResetWrapper>>()
-        .unwrap();
-
-    let input_definition = Operation::from(PragmaActiveReset::new(0));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaActiveResetWrapper>();
+        let new_op = operation
+            .call1((0,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaActiveResetWrapper>>()
+            .unwrap();
 
-    let pragma_wrapper = new_op.extract::<PragmaActiveResetWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((1,))
-        .unwrap()
-        .cast_as::<PyCell<PragmaActiveResetWrapper>>()
+        let input_definition = Operation::from(PragmaActiveReset::new(0));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaActiveResetWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaActiveResetWrapper { internal: PragmaActiveReset { qubit: 0 } }"
-    );
+        let pragma_wrapper = new_op.extract::<PragmaActiveResetWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((1,))
+            .unwrap()
+            .cast_as::<PyCell<PragmaActiveResetWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaActiveResetWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaActiveResetWrapper { internal: PragmaActiveReset { qubit: 0 } }"
+        );
+    })
 }
 
 /// Test PragmaStartDecompositionBlock new() function
 #[test]
 fn test_pyo3_new_start_decomposition_block() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaStartDecompositionBlockWrapper>();
-    let new_op = operation
-        .call1((vec![0], reordering()))
-        .unwrap()
-        .cast_as::<PyCell<PragmaStartDecompositionBlockWrapper>>()
-        .unwrap();
-
-    let input_definition =
-        Operation::from(PragmaStartDecompositionBlock::new(vec![0], reordering()));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaStartDecompositionBlockWrapper>();
+        let new_op = operation
+            .call1((vec![0], reordering()))
+            .unwrap()
+            .cast_as::<PyCell<PragmaStartDecompositionBlockWrapper>>()
+            .unwrap();
 
-    let pragma_wrapper = new_op
-        .extract::<PragmaStartDecompositionBlockWrapper>()
-        .unwrap();
-    let new_op_diff = operation
-        .call1((vec![1], reordering()))
-        .unwrap()
-        .cast_as::<PyCell<PragmaStartDecompositionBlockWrapper>>()
-        .unwrap();
-    let pragma_wrapper_diff = new_op_diff
-        .extract::<PragmaStartDecompositionBlockWrapper>()
+        let input_definition =
+            Operation::from(PragmaStartDecompositionBlock::new(vec![0], reordering()));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaStartDecompositionBlockWrapper { internal: PragmaStartDecompositionBlock { qubits: [0], reordering_dictionary: {0: 0} } }"
-    );
+        let pragma_wrapper = new_op
+            .extract::<PragmaStartDecompositionBlockWrapper>()
+            .unwrap();
+        let new_op_diff = operation
+            .call1((vec![1], reordering()))
+            .unwrap()
+            .cast_as::<PyCell<PragmaStartDecompositionBlockWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff
+            .extract::<PragmaStartDecompositionBlockWrapper>()
+            .unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaStartDecompositionBlockWrapper { internal: PragmaStartDecompositionBlock { qubits: [0], reordering_dictionary: {0: 0} } }"
+        );
+    })
 }
 
 /// Test PragmaStopDecompositionBlock new() function
 #[test]
 fn test_pyo3_new_stop_decomposition_block() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaStopDecompositionBlockWrapper>();
-    let new_op = operation
-        .call1((vec![0],))
-        .unwrap()
-        .cast_as::<PyCell<PragmaStopDecompositionBlockWrapper>>()
-        .unwrap();
-
-    let input_definition = Operation::from(PragmaStopDecompositionBlock::new(vec![0]));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaStopDecompositionBlockWrapper>();
+        let new_op = operation
+            .call1((vec![0],))
+            .unwrap()
+            .cast_as::<PyCell<PragmaStopDecompositionBlockWrapper>>()
+            .unwrap();
 
-    let pragma_wrapper = new_op
-        .extract::<PragmaStopDecompositionBlockWrapper>()
-        .unwrap();
-    let new_op_diff = operation
-        .call1((vec![1],))
-        .unwrap()
-        .cast_as::<PyCell<PragmaStopDecompositionBlockWrapper>>()
-        .unwrap();
-    let pragma_wrapper_diff = new_op_diff
-        .extract::<PragmaStopDecompositionBlockWrapper>()
+        let input_definition = Operation::from(PragmaStopDecompositionBlock::new(vec![0]));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaStopDecompositionBlockWrapper { internal: PragmaStopDecompositionBlock { qubits: [0] } }"
-    );
+        let pragma_wrapper = new_op
+            .extract::<PragmaStopDecompositionBlockWrapper>()
+            .unwrap();
+        let new_op_diff = operation
+            .call1((vec![1],))
+            .unwrap()
+            .cast_as::<PyCell<PragmaStopDecompositionBlockWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff
+            .extract::<PragmaStopDecompositionBlockWrapper>()
+            .unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaStopDecompositionBlockWrapper { internal: PragmaStopDecompositionBlock { qubits: [0] } }"
+        );
+    })
 }
 
 /// Test PragmaDamping new() function
 #[test]
 fn test_pyo3_new_damping() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaDampingWrapper>();
-    let new_op = operation
-        .call1((0, 0.005, 0.02))
-        .unwrap()
-        .cast_as::<PyCell<PragmaDampingWrapper>>()
-        .unwrap();
-    let input_definition = Operation::from(PragmaDamping::new(
-        0,
-        CalculatorFloat::from(0.005),
-        CalculatorFloat::from(0.02),
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-    let result = operation.call1((0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaDampingWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((1, 0.005, 0.02))
-        .unwrap()
-        .cast_as::<PyCell<PragmaDampingWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaDampingWrapper>();
+        let new_op = operation
+            .call1((0, 0.005, 0.02))
+            .unwrap()
+            .cast_as::<PyCell<PragmaDampingWrapper>>()
+            .unwrap();
+        let input_definition = Operation::from(PragmaDamping::new(
+            0,
+            CalculatorFloat::from(0.005),
+            CalculatorFloat::from(0.02),
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaDampingWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
+
+        // Error initialisation
+        let result = operation.call1((0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+        let result = operation.call1((0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaDampingWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((1, 0.005, 0.02))
+            .unwrap()
+            .cast_as::<PyCell<PragmaDampingWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaDampingWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaDampingWrapper { internal: PragmaDamping { qubit: 0, gate_time: Float(0.005), rate: Float(0.02) } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaDampingWrapper { internal: PragmaDamping { qubit: 0, gate_time: Float(0.005), rate: Float(0.02) } }"
+        );
+    })
 }
 
 /// Test PragmaDepolarising new() function
 #[test]
 fn test_pyo3_new_depolarising() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaDepolarisingWrapper>();
-    let new_op = operation
-        .call1((0, 0.005, 0.02))
-        .unwrap()
-        .cast_as::<PyCell<PragmaDepolarisingWrapper>>()
-        .unwrap();
-    let input_definition = Operation::from(PragmaDepolarising::new(
-        0,
-        CalculatorFloat::from(0.005),
-        CalculatorFloat::from(0.02),
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-    let result = operation.call1((0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaDepolarisingWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((1, 0.005, 0.02))
-        .unwrap()
-        .cast_as::<PyCell<PragmaDepolarisingWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaDepolarisingWrapper>();
+        let new_op = operation
+            .call1((0, 0.005, 0.02))
+            .unwrap()
+            .cast_as::<PyCell<PragmaDepolarisingWrapper>>()
+            .unwrap();
+        let input_definition = Operation::from(PragmaDepolarising::new(
+            0,
+            CalculatorFloat::from(0.005),
+            CalculatorFloat::from(0.02),
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaDepolarisingWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
+
+        // Error initialisation
+        let result = operation.call1((0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+        let result = operation.call1((0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaDepolarisingWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((1, 0.005, 0.02))
+            .unwrap()
+            .cast_as::<PyCell<PragmaDepolarisingWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaDepolarisingWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaDepolarisingWrapper { internal: PragmaDepolarising { qubit: 0, gate_time: Float(0.005), rate: Float(0.02) } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaDepolarisingWrapper { internal: PragmaDepolarising { qubit: 0, gate_time: Float(0.005), rate: Float(0.02) } }"
+        );
+    })
 }
 
 /// Test PragmaDephasing new() function
 #[test]
 fn test_pyo3_new_dephasing() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaDephasingWrapper>();
-    let new_op = operation
-        .call1((0, 0.005, 0.02))
-        .unwrap()
-        .cast_as::<PyCell<PragmaDephasingWrapper>>()
-        .unwrap();
-    let input_definition = Operation::from(PragmaDephasing::new(
-        0,
-        CalculatorFloat::from(0.005),
-        CalculatorFloat::from(0.02),
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-    let result = operation.call1((0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaDephasingWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((1, 0.005, 0.02))
-        .unwrap()
-        .cast_as::<PyCell<PragmaDephasingWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaDephasingWrapper>();
+        let new_op = operation
+            .call1((0, 0.005, 0.02))
+            .unwrap()
+            .cast_as::<PyCell<PragmaDephasingWrapper>>()
+            .unwrap();
+        let input_definition = Operation::from(PragmaDephasing::new(
+            0,
+            CalculatorFloat::from(0.005),
+            CalculatorFloat::from(0.02),
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaDephasingWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
+
+        // Error initialisation
+        let result = operation.call1((0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+        let result = operation.call1((0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaDephasingWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((1, 0.005, 0.02))
+            .unwrap()
+            .cast_as::<PyCell<PragmaDephasingWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaDephasingWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaDephasingWrapper { internal: PragmaDephasing { qubit: 0, gate_time: Float(0.005), rate: Float(0.02) } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaDephasingWrapper { internal: PragmaDephasing { qubit: 0, gate_time: Float(0.005), rate: Float(0.02) } }"
+        );
+    })
 }
 
 /// Test PragmaRandomNoise new() function
 #[test]
 fn test_pyo3_new_randomnoise() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaRandomNoiseWrapper>();
-    let new_op = operation
-        .call1((0, 0.005, 0.02, 0.01))
-        .unwrap()
-        .cast_as::<PyCell<PragmaRandomNoiseWrapper>>()
-        .unwrap();
-    let input_definition = Operation::from(PragmaRandomNoise::new(
-        0,
-        CalculatorFloat::from(0.005),
-        CalculatorFloat::from(0.02),
-        CalculatorFloat::from(0.01),
-    ));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((0, vec!["fails"], 0.0, 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-    let result = operation.call1((0, 0.0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-    let result = operation.call1((0, 0.0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaRandomNoiseWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((1, 0.005, 0.02, 0.01))
-        .unwrap()
-        .cast_as::<PyCell<PragmaRandomNoiseWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaRandomNoiseWrapper>();
+        let new_op = operation
+            .call1((0, 0.005, 0.02, 0.01))
+            .unwrap()
+            .cast_as::<PyCell<PragmaRandomNoiseWrapper>>()
+            .unwrap();
+        let input_definition = Operation::from(PragmaRandomNoise::new(
+            0,
+            CalculatorFloat::from(0.005),
+            CalculatorFloat::from(0.02),
+            CalculatorFloat::from(0.01),
+        ));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaRandomNoiseWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
+
+        // Error initialisation
+        let result = operation.call1((0, vec!["fails"], 0.0, 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+        let result = operation.call1((0, 0.0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+        let result = operation.call1((0, 0.0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaRandomNoiseWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((1, 0.005, 0.02, 0.01))
+            .unwrap()
+            .cast_as::<PyCell<PragmaRandomNoiseWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaRandomNoiseWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaRandomNoiseWrapper { internal: PragmaRandomNoise { qubit: 0, gate_time: Float(0.005), depolarising_rate: Float(0.02), dephasing_rate: Float(0.01) } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaRandomNoiseWrapper { internal: PragmaRandomNoise { qubit: 0, gate_time: Float(0.005), depolarising_rate: Float(0.02), dephasing_rate: Float(0.01) } }"
+        );
+    })
 }
 
 /// Test PragmaGeneralNoise new() function
 #[test]
 fn test_pyo3_new_general_noise() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation = py.get_type::<PragmaGeneralNoiseWrapper>();
-    let to_get_operators = Operation::from(PragmaGeneralNoise::new(
-        0,
-        CalculatorFloat::from(0.005),
-        operators(),
-    ));
-    let convert_to_get_operators = convert_operation_to_pyobject(to_get_operators)
-        .unwrap()
-        .clone();
-    let operators_op = convert_to_get_operators.call_method0(py, "rates").unwrap();
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation = py.get_type::<PragmaGeneralNoiseWrapper>();
+        let to_get_operators = Operation::from(PragmaGeneralNoise::new(
+            0,
+            CalculatorFloat::from(0.005),
+            operators(),
+        ));
+        let convert_to_get_operators = convert_operation_to_pyobject(to_get_operators)
+            .unwrap()
+            .clone();
+        let operators_op = convert_to_get_operators.call_method0(py, "rates").unwrap();
 
-    let new_op = operation
-        .call1((0, 0.005, operators_op.clone()))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGeneralNoiseWrapper>>()
+        let new_op = operation
+            .call1((0, 0.005, operators_op.clone()))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGeneralNoiseWrapper>>()
+            .unwrap();
+
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (convert_to_get_operators.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison_copy);
 
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (convert_to_get_operators.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-
-    // Error initialisation
-    let result = operation.call1((0, vec!["fails"], 0.0, operators_op.clone()));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation.call1((0, 0.0, vec!["fails"], operators_op.clone()));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let pragma_wrapper = new_op.extract::<PragmaGeneralNoiseWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1((1, 0.005, operators_op))
-        .unwrap()
-        .cast_as::<PyCell<PragmaGeneralNoiseWrapper>>()
-        .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaGeneralNoiseWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        // Error initialisation
+        let result = operation.call1((0, vec!["fails"], 0.0, operators_op.clone()));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation.call1((0, 0.0, vec!["fails"], operators_op.clone()));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let pragma_wrapper = new_op.extract::<PragmaGeneralNoiseWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1((1, 0.005, operators_op))
+            .unwrap()
+            .cast_as::<PyCell<PragmaGeneralNoiseWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaGeneralNoiseWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaGeneralNoiseWrapper { internal: PragmaGeneralNoise { qubit: 0, gate_time: Float(0.005), rates: [[1.0, 0.0, 0.0],\n [0.0, 1.0, 0.0],\n [0.0, 0.0, 1.0]], shape=[3, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2 } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaGeneralNoiseWrapper { internal: PragmaGeneralNoise { qubit: 0, gate_time: Float(0.005), rates: [[1.0, 0.0, 0.0],\n [0.0, 1.0, 0.0],\n [0.0, 0.0, 1.0]], shape=[3, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2 } }"
+        );
+    })
 }
 
 /// Test PragmaConditional new() function
 #[test]
 fn test_pyo3_new_conditional() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = py.get_type::<PragmaConditionalWrapper>();
-    let new_op = operation
-        .call1(("ro".to_string(), 0, new_circuit(py)))
-        .unwrap()
-        .cast_as::<PyCell<PragmaConditionalWrapper>>()
-        .unwrap();
-
-    let input_definition =
-        Operation::from(PragmaConditional::new("ro".to_string(), 0, Circuit::new()));
-    let copy_param = convert_operation_to_pyobject(input_definition)
-        .unwrap()
-        .clone();
-    let comparison_copy = bool::extract(
-        new_op
-            .call_method1("__eq__", (copy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
+    Python::with_gil(|py| -> () {
+        let operation = py.get_type::<PragmaConditionalWrapper>();
+        let new_op = operation
+            .call1(("ro".to_string(), 0, new_circuit(py)))
+            .unwrap()
+            .cast_as::<PyCell<PragmaConditionalWrapper>>()
+            .unwrap();
 
-    let pragma_wrapper = new_op.extract::<PragmaConditionalWrapper>().unwrap();
-    let new_op_diff = operation
-        .call1(("ro".to_string(), 2, new_circuit(py)))
-        .unwrap()
-        .cast_as::<PyCell<PragmaConditionalWrapper>>()
+        let input_definition =
+            Operation::from(PragmaConditional::new("ro".to_string(), 0, Circuit::new()));
+        let copy_param = convert_operation_to_pyobject(input_definition)
+            .unwrap()
+            .clone();
+        let comparison_copy = bool::extract(
+            new_op
+                .call_method1("__eq__", (copy_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let pragma_wrapper_diff = new_op_diff.extract::<PragmaConditionalWrapper>().unwrap();
-    let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
-    assert!(helper_eq);
+        assert!(comparison_copy);
+
+        let pragma_wrapper = new_op.extract::<PragmaConditionalWrapper>().unwrap();
+        let new_op_diff = operation
+            .call1(("ro".to_string(), 2, new_circuit(py)))
+            .unwrap()
+            .cast_as::<PyCell<PragmaConditionalWrapper>>()
+            .unwrap();
+        let pragma_wrapper_diff = new_op_diff.extract::<PragmaConditionalWrapper>().unwrap();
+        let helper_ne: bool = pragma_wrapper_diff != pragma_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = pragma_wrapper == pragma_wrapper.clone();
+        assert!(helper_eq);
 
-    assert_eq!(
-        format!("{:?}", pragma_wrapper),
-        "PragmaConditionalWrapper { internal: PragmaConditional { condition_register: \"ro\", condition_index: 0, circuit: Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion } } }"
-    );
+        assert_eq!(
+            format!("{:?}", pragma_wrapper),
+            "PragmaConditionalWrapper { internal: PragmaConditional { condition_register: \"ro\", condition_index: 0, circuit: Circuit { definitions: [], operations: [], _roqoqo_version: RoqoqoVersion } } }"
+        );
+    })
 }
 
 // test remap_qubits() function returning an error.
@@ -2513,12 +2496,12 @@ fn test_pyo3_new_conditional() {
 fn test_pyo3_remapqubits_error(input_operation: Operation) {
     // preparation
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    // remap qubits
-    let qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        // remap qubits
+        let qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
diff --git a/qoqo/tests/integration/operations/single_qubit_gate_operations.rs b/qoqo/tests/integration/operations/single_qubit_gate_operations.rs
index 3e1a4759..65be52d0 100644
--- a/qoqo/tests/integration/operations/single_qubit_gate_operations.rs
+++ b/qoqo/tests/integration/operations/single_qubit_gate_operations.rs
@@ -60,40 +60,40 @@ fn convert_cf_to_pyobject(
 fn test_new_paulix(input_operation: Operation, arguments: (u32,), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<PauliXWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<PauliXWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<PauliXWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<PauliXWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<PauliXWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<PauliXWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<PauliXWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "PauliXWrapper { internal: PauliX { qubit: 2 } }"
-    );
+        assert!(comparison);
+
+        let def_wrapper = operation_py.extract::<PauliXWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<PauliXWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<PauliXWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "PauliXWrapper { internal: PauliX { qubit: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for PauliY
@@ -102,40 +102,40 @@ fn test_new_paulix(input_operation: Operation, arguments: (u32,), method: &str)
 fn test_new_pauliy(input_operation: Operation, arguments: (u32,), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<PauliYWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<PauliYWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<PauliYWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<PauliYWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<PauliYWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<PauliYWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<PauliYWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "PauliYWrapper { internal: PauliY { qubit: 2 } }"
-    );
+        assert!(comparison);
+
+        let def_wrapper = operation_py.extract::<PauliYWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<PauliYWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<PauliYWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "PauliYWrapper { internal: PauliY { qubit: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for PauliZ
@@ -144,40 +144,40 @@ fn test_new_pauliy(input_operation: Operation, arguments: (u32,), method: &str)
 fn test_new_pauliz(input_operation: Operation, arguments: (u32,), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<PauliZWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<PauliZWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<PauliZWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<PauliZWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<PauliZWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<PauliZWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<PauliZWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "PauliZWrapper { internal: PauliZ { qubit: 2 } }"
-    );
+        assert!(comparison);
+
+        let def_wrapper = operation_py.extract::<PauliZWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<PauliZWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<PauliZWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "PauliZWrapper { internal: PauliZ { qubit: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for SqrtPauliX
@@ -186,40 +186,40 @@ fn test_new_pauliz(input_operation: Operation, arguments: (u32,), method: &str)
 fn test_new_sqrtpaulix(input_operation: Operation, arguments: (u32,), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<SqrtPauliXWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<SqrtPauliXWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<SqrtPauliXWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<SqrtPauliXWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<SqrtPauliXWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<SqrtPauliXWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<SqrtPauliXWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "SqrtPauliXWrapper { internal: SqrtPauliX { qubit: 2 } }"
-    );
+        assert!(comparison);
+
+        let def_wrapper = operation_py.extract::<SqrtPauliXWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<SqrtPauliXWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<SqrtPauliXWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "SqrtPauliXWrapper { internal: SqrtPauliX { qubit: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for InvSqrtPauliX
@@ -228,40 +228,40 @@ fn test_new_sqrtpaulix(input_operation: Operation, arguments: (u32,), method: &s
 fn test_new_invsqrtpaulix(input_operation: Operation, arguments: (u32,), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<InvSqrtPauliXWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<InvSqrtPauliXWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<InvSqrtPauliXWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<InvSqrtPauliXWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<InvSqrtPauliXWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<InvSqrtPauliXWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<InvSqrtPauliXWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "InvSqrtPauliXWrapper { internal: InvSqrtPauliX { qubit: 2 } }"
-    );
+        assert!(comparison);
+
+        let def_wrapper = operation_py.extract::<InvSqrtPauliXWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<InvSqrtPauliXWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<InvSqrtPauliXWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "InvSqrtPauliXWrapper { internal: InvSqrtPauliX { qubit: 2 } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(SGate::new(1)), (1,), "__eq__"; "SGate_eq")]
@@ -269,40 +269,40 @@ fn test_new_invsqrtpaulix(input_operation: Operation, arguments: (u32,), method:
 fn test_new_sgate(input_operation: Operation, arguments: (u32,), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<SGateWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<SGateWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<SGateWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<SGateWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<SGateWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<SGateWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<SGateWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "SGateWrapper { internal: SGate { qubit: 2 } }"
-    );
+        assert!(comparison);
+
+        let def_wrapper = operation_py.extract::<SGateWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<SGateWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<SGateWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "SGateWrapper { internal: SGate { qubit: 2 } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(TGate::new(1)), (1,), "__eq__"; "TGate_eq")]
@@ -310,82 +310,81 @@ fn test_new_sgate(input_operation: Operation, arguments: (u32,), method: &str) {
 fn test_new_tgate(input_operation: Operation, arguments: (u32,), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<TGateWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<TGateWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<TGateWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<TGateWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<TGateWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<TGateWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<TGateWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "TGateWrapper { internal: TGate { qubit: 2 } }"
-    );
+        assert!(comparison);
+
+        let def_wrapper = operation_py.extract::<TGateWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<TGateWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<TGateWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "TGateWrapper { internal: TGate { qubit: 2 } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(Hadamard::new(1)), (1,), "__eq__"; "Hadamard_eq")]
 #[test_case(Operation::from(Hadamard::new(1)), (0,), "__ne__"; "Hadamard_ne")]
 fn test_new_hadamard(input_operation: Operation, arguments: (u32,), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
-
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<HadamardWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<HadamardWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<HadamardWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<HadamardWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<HadamardWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<HadamardWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<HadamardWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "HadamardWrapper { internal: Hadamard { qubit: 2 } }"
-    );
+        assert!(comparison);
+
+        let def_wrapper = operation_py.extract::<HadamardWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<HadamardWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<HadamardWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "HadamardWrapper { internal: Hadamard { qubit: 2 } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(RotateX::new(1, CalculatorFloat::ZERO)), (1, 0.0,), "__eq__"; "RotateX_eq")]
@@ -393,47 +392,46 @@ fn test_new_hadamard(input_operation: Operation, arguments: (u32,), method: &str
 fn test_new_rotatex(input_operation: Operation, arguments: (u32, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<RotateXWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<RotateXWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<RotateXWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<RotateXWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<RotateXWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<RotateXWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<RotateXWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "RotateXWrapper { internal: RotateX { qubit: 2, theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<RotateXWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<RotateXWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<RotateXWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "RotateXWrapper { internal: RotateX { qubit: 2, theta: Float(0.0) } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(RotateY::new(1, CalculatorFloat::ZERO)), (1, 0.0,), "__eq__"; "RotateY_eq")]
@@ -441,47 +439,46 @@ fn test_new_rotatex(input_operation: Operation, arguments: (u32, f64), method: &
 fn test_new_rotatey(input_operation: Operation, arguments: (u32, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<RotateYWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<RotateYWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<RotateYWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<RotateYWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<RotateYWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<RotateYWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<RotateYWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "RotateYWrapper { internal: RotateY { qubit: 2, theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<RotateYWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<RotateYWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<RotateYWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "RotateYWrapper { internal: RotateY { qubit: 2, theta: Float(0.0) } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(RotateZ::new(1, CalculatorFloat::ZERO)), (1, 0.0,), "__eq__"; "RotateZ_eq")]
@@ -489,48 +486,47 @@ fn test_new_rotatey(input_operation: Operation, arguments: (u32, f64), method: &
 fn test_new_rotatez(input_operation: Operation, arguments: (u32, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<RotateZWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<RotateZWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<RotateZWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<RotateZWrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<RotateZWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<RotateZWrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<RotateZWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "RotateZWrapper { internal: RotateZ { qubit: 2, theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<RotateZWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<RotateZWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<RotateZWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "RotateZWrapper { internal: RotateZ { qubit: 2, theta: Float(0.0) } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(PhaseShiftState0::new(1, CalculatorFloat::ZERO)), (1, 0.0,), "__eq__"; "PhaseShiftState0_eq")]
@@ -538,48 +534,47 @@ fn test_new_rotatez(input_operation: Operation, arguments: (u32, f64), method: &
 fn test_new_phaseshiftstate0(input_operation: Operation, arguments: (u32, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<PhaseShiftState0Wrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<PhaseShiftState0Wrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<PhaseShiftState0Wrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<PhaseShiftState0Wrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<PhaseShiftState0Wrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<PhaseShiftState0Wrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<PhaseShiftState0Wrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "PhaseShiftState0Wrapper { internal: PhaseShiftState0 { qubit: 2, theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<PhaseShiftState0Wrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<PhaseShiftState0Wrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<PhaseShiftState0Wrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "PhaseShiftState0Wrapper { internal: PhaseShiftState0 { qubit: 2, theta: Float(0.0) } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(PhaseShiftState1::new(1, CalculatorFloat::ZERO)), (1, 0.0,), "__eq__"; "PhaseShiftState1_eq")]
@@ -587,48 +582,47 @@ fn test_new_phaseshiftstate0(input_operation: Operation, arguments: (u32, f64),
 fn test_new_phaseshiftstate1(input_operation: Operation, arguments: (u32, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<PhaseShiftState1Wrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<PhaseShiftState1Wrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<PhaseShiftState1Wrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<PhaseShiftState1Wrapper>>()
+            .unwrap();
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<PhaseShiftState1Wrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<PhaseShiftState1Wrapper>>()
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<PhaseShiftState1Wrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "PhaseShiftState1Wrapper { internal: PhaseShiftState1 { qubit: 2, theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<PhaseShiftState1Wrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<PhaseShiftState1Wrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<PhaseShiftState1Wrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "PhaseShiftState1Wrapper { internal: PhaseShiftState1 { qubit: 2, theta: Float(0.0) } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(
@@ -650,57 +644,56 @@ fn test_new_phaseshiftstate1(input_operation: Operation, arguments: (u32, f64),
 fn test_new_rotate(input_operation: Operation, arguments: (u32, f64, f64, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<RotateAroundSphericalAxisWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<RotateAroundSphericalAxisWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, vec!["fails"], 0.0, 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-    let result = operation_type.call1((0, 0.0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-    let result = operation_type.call1((0, 0.0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py
-        .extract::<RotateAroundSphericalAxisWrapper>()
-        .unwrap();
-    let new_op_diff = operation_type
-        .call1((2, 0.0, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<RotateAroundSphericalAxisWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff
-        .extract::<RotateAroundSphericalAxisWrapper>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<RotateAroundSphericalAxisWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<RotateAroundSphericalAxisWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "RotateAroundSphericalAxisWrapper { internal: RotateAroundSphericalAxis { qubit: 2, theta: Float(0.0), spherical_theta: Float(0.0), spherical_phi: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, vec!["fails"], 0.0, 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+        let result = operation_type.call1((0, 0.0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+        let result = operation_type.call1((0, 0.0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py
+            .extract::<RotateAroundSphericalAxisWrapper>()
+            .unwrap();
+        let new_op_diff = operation_type
+            .call1((2, 0.0, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<RotateAroundSphericalAxisWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff
+            .extract::<RotateAroundSphericalAxisWrapper>()
+            .unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "RotateAroundSphericalAxisWrapper { internal: RotateAroundSphericalAxis { qubit: 2, theta: Float(0.0), spherical_theta: Float(0.0), spherical_phi: Float(0.0) } }"
+        );
+    })
 }
 
 #[test_case(Operation::from(
@@ -730,63 +723,62 @@ fn test_new_singlequbitgate(
 ) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<SingleQubitGateWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<SingleQubitGateWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, vec!["fails"], 0.0, 0.0, 0.0, 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 0.0, vec!["fails"], 0.0, 0.0, 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 0.0, 0.0, vec!["fails"], 0.0, 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 0.0, 0.0, 0.0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 0.0, 0.0, 0.0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<SingleQubitGateWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((2, 0.0, 0.0, 0.0, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<SingleQubitGateWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<SingleQubitGateWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<SingleQubitGateWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<SingleQubitGateWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "SingleQubitGateWrapper { internal: SingleQubitGate { qubit: 2, alpha_r: Float(0.0), alpha_i: Float(0.0), beta_r: Float(0.0), beta_i: Float(0.0), global_phase: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, vec!["fails"], 0.0, 0.0, 0.0, 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 0.0, vec!["fails"], 0.0, 0.0, 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 0.0, 0.0, vec!["fails"], 0.0, 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 0.0, 0.0, 0.0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 0.0, 0.0, 0.0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<SingleQubitGateWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((2, 0.0, 0.0, 0.0, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<SingleQubitGateWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<SingleQubitGateWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "SingleQubitGateWrapper { internal: SingleQubitGate { qubit: 2, alpha_r: Float(0.0), alpha_i: Float(0.0), beta_r: Float(0.0), beta_i: Float(0.0), global_phase: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test is_parametrized() function for SingleQubitGate Operations
@@ -817,16 +809,16 @@ fn test_new_singlequbitgate(
 #[test_case(Operation::from(PhaseShiftState1::new(1, CalculatorFloat::from("theta"))); "PhaseShiftState1")]
 fn test_pyo3_is_parametrized(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    assert!(bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        assert!(bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 /// Test is_parametrized = false for SingleQubitGate Operations
@@ -865,16 +857,16 @@ fn test_pyo3_is_parametrized(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(1, CalculatorFloat::from(0))); "PhaseShiftState1")]
 fn test_pyo3_is_not_parametrized(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    assert!(!bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        assert!(!bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 /// Test theta() function for Rotations
@@ -895,15 +887,16 @@ fn test_pyo3_is_not_parametrized(input_operation: Operation) {
 #[test_case(CalculatorFloat::from(0), Operation::from(PhaseShiftState1::new(1, CalculatorFloat::from(0))); "PhaseShiftState1")]
 fn test_pyo3_theta(theta: CalculatorFloat, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let theta_op: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(operation.call_method0(py, "theta").unwrap().as_ref(py))
-            .unwrap();
-    let theta_param: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, theta)).unwrap();
-    assert_eq!(theta_op.cf_internal, theta_param.cf_internal);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let theta_op: CalculatorFloatWrapper = CalculatorFloatWrapper::extract(
+            operation.call_method0(py, "theta").unwrap().as_ref(py),
+        )
+        .unwrap();
+        let theta_param: CalculatorFloatWrapper =
+            CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, theta)).unwrap();
+        assert_eq!(theta_op.cf_internal, theta_param.cf_internal);
+    })
 }
 
 /// Test qubit() function for SingleQubitGate Operations
@@ -931,12 +924,12 @@ fn test_pyo3_theta(theta: CalculatorFloat, input_operation: Operation) {
 #[test_case(1, Operation::from(PhaseShiftState1::new(1, CalculatorFloat::from(0))); "PhaseShiftState1")]
 fn test_pyo3_qubit(qubit: usize, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let qubit_op: usize =
-        usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
-    assert_eq!(qubit_op, qubit);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let qubit_op: usize =
+            usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
+        assert_eq!(qubit_op, qubit);
+    })
 }
 
 /// Test RotateX hqslang() function for SingleQubitGate Operations
@@ -974,12 +967,12 @@ fn test_pyo3_qubit(qubit: usize, input_operation: Operation) {
 #[test_case("PhaseShiftState1", Operation::from(PhaseShiftState1::new(1, CalculatorFloat::from(0))); "PhaseShiftState1")]
 fn test_pyo3_hqslang(name: &'static str, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let name_op: String =
-        String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
-    assert_eq!(name_op, name.to_string());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let name_op: String =
+            String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
+        assert_eq!(name_op, name.to_string());
+    })
 }
 
 /// Test tags() function for SingleQubitGate Operations
@@ -1140,15 +1133,15 @@ fn test_pyo3_hqslang(name: &'static str, input_operation: Operation) {
     "PhaseShiftState1")]
 fn test_pyo3_tags(input_operation: Operation, tags: Vec<&str>) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let tags_op: Vec<String> =
-        Vec::<String>::extract(operation.call_method0(py, "tags").unwrap().as_ref(py)).unwrap();
-    assert_eq!(tags_op.len(), tags.len());
-    for i in 0..tags.len() {
-        assert_eq!(tags_op[i], tags[i]);
-    }
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let tags_op: Vec<String> =
+            Vec::<String>::extract(operation.call_method0(py, "tags").unwrap().as_ref(py)).unwrap();
+        assert_eq!(tags_op.len(), tags.len());
+        for i in 0..tags.len() {
+            assert_eq!(tags_op[i], tags[i]);
+        }
+    })
 }
 
 /// Test remap_qubits() function for SingleQubitGate Operations
@@ -1187,25 +1180,25 @@ fn test_pyo3_tags(input_operation: Operation, tags: Vec<&str>) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from(0))); "PhaseShiftState1")]
 fn test_pyo3_remapqubits(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    // test initial qubit
-    let qubit: usize =
-        usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
-    assert_eq!(qubit.clone(), 0);
-    // remap qubits
-    let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    qubit_mapping.insert(0, 1);
-    let result = operation
-        .call_method1(py, "remap_qubits", (qubit_mapping,))
-        .unwrap();
-    // test re-mapped qubit
-    let qubit_new: usize =
-        usize::extract(result.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
-    assert_eq!(qubit_new.clone(), 1);
-    // test that initial and rempapped qubits are different
-    assert_ne!(qubit, qubit_new);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        // test initial qubit
+        let qubit: usize =
+            usize::extract(operation.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
+        assert_eq!(qubit.clone(), 0);
+        // remap qubits
+        let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        qubit_mapping.insert(0, 1);
+        let result = operation
+            .call_method1(py, "remap_qubits", (qubit_mapping,))
+            .unwrap();
+        // test re-mapped qubit
+        let qubit_new: usize =
+            usize::extract(result.call_method0(py, "qubit").unwrap().as_ref(py)).unwrap();
+        assert_eq!(qubit_new.clone(), 1);
+        // test that initial and rempapped qubits are different
+        assert_ne!(qubit, qubit_new);
+    })
 }
 
 // test remap_qubits() function returning an error.
@@ -1245,14 +1238,14 @@ fn test_pyo3_remapqubits(input_operation: Operation) {
 fn test_pyo3_remapqubits_error(input_operation: Operation) {
     // preparation
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    // remap qubits
-    let qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        // remap qubits
+        let qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test unitary_matrix() function for SingleQubitGate Operations
@@ -1291,21 +1284,21 @@ fn test_pyo3_remapqubits_error(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from(2.3))); "PhaseShiftState1")]
 fn test_pyo3_unitarymatrix(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let py_result = operation.call_method0(py, "unitary_matrix").unwrap();
-    let result_matrix = py_result
-        .cast_as::<PyArray2<Complex64>>(py)
-        .unwrap()
-        .to_owned_array();
-
-    // compare to reference matrix obtained in Rust directly (without passing to Python)
-    let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
-    let rust_matrix: Result<Array2<Complex64>, RoqoqoError> = gate.unitary_matrix();
-    let test_matrix: Array2<Complex64> = rust_matrix.unwrap();
-
-    assert_eq!(result_matrix, test_matrix);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let py_result = operation.call_method0(py, "unitary_matrix").unwrap();
+        let result_matrix = py_result
+            .cast_as::<PyArray2<Complex64>>(py)
+            .unwrap()
+            .to_owned_array();
+
+        // compare to reference matrix obtained in Rust directly (without passing to Python)
+        let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
+        let rust_matrix: Result<Array2<Complex64>, RoqoqoError> = gate.unitary_matrix();
+        let test_matrix: Array2<Complex64> = rust_matrix.unwrap();
+
+        assert_eq!(result_matrix, test_matrix);
+    })
 }
 
 /// Test unitary_matrix() function for SingleQubitGate Operations for the error case
@@ -1325,12 +1318,12 @@ fn test_pyo3_unitarymatrix(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from("PI"))); "PhaseShiftState1")]
 fn test_pyo3_unitarymatrix_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let py_result = operation.call_method0(py, "unitary_matrix");
-    let result_ref = py_result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let py_result = operation.call_method0(py, "unitary_matrix");
+        let result_ref = py_result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test unitary_matrix() function for SingleQubitGate returning an error
@@ -1358,12 +1351,12 @@ fn test_pyo3_unitarymatrix_error(input_operation: Operation) {
 ]
 fn test_pyo3_unitarymatrix_singlequbitgate(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let py_result = operation.call_method0(py, "unitary_matrix");
-    let result_ref = py_result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let py_result = operation.call_method0(py, "unitary_matrix");
+        let result_ref = py_result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test copy and deepcopy functions
@@ -1402,29 +1395,29 @@ fn test_pyo3_unitarymatrix_singlequbitgate(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from(0.0))); "PhaseShiftState1")]
 fn test_pyo3_copy_deepcopy(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let copy_op = operation.call_method0(py, "__copy__").unwrap();
-    let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
-    let copy_deepcopy_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        copy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-    let comparison_deepcopy = bool::extract(
-        deepcopy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let copy_op = operation.call_method0(py, "__copy__").unwrap();
+        let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
+        let copy_deepcopy_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            copy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+        let comparison_deepcopy = bool::extract(
+            deepcopy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 /// Test alpha_r obtained via the python interface for SingleQubitGate Operations
@@ -1463,23 +1456,23 @@ fn test_pyo3_copy_deepcopy(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from(0.0))); "PhaseShiftState1")]
 fn test_pyo3_alpha_r(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-
-    let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
-    let alpha_r = gate.alpha_r();
-    let alpha_r_param: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, alpha_r)).unwrap();
-    let method_op = operation.call_method0(py, "alpha_r").unwrap();
-    let comparison_alpha_r = bool::extract(
-        method_op
-            .as_ref(py)
-            .call_method1("__eq__", (alpha_r_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_alpha_r);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+
+        let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
+        let alpha_r = gate.alpha_r();
+        let alpha_r_param: CalculatorFloatWrapper =
+            CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, alpha_r)).unwrap();
+        let method_op = operation.call_method0(py, "alpha_r").unwrap();
+        let comparison_alpha_r = bool::extract(
+            method_op
+                .as_ref(py)
+                .call_method1("__eq__", (alpha_r_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_alpha_r);
+    })
 }
 
 /// Test alpha_i obtained via the python interface for SingleQubitGate Operations
@@ -1518,23 +1511,23 @@ fn test_pyo3_alpha_r(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from(0.0))); "PhaseShiftState1")]
 fn test_pyo3_alpha_i(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-
-    let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
-    let alpha_i = gate.alpha_i();
-    let alpha_i_param: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, alpha_i)).unwrap();
-    let method_op = operation.call_method0(py, "alpha_i").unwrap();
-    let comparison_alpha_i = bool::extract(
-        method_op
-            .as_ref(py)
-            .call_method1("__eq__", (alpha_i_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_alpha_i);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+
+        let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
+        let alpha_i = gate.alpha_i();
+        let alpha_i_param: CalculatorFloatWrapper =
+            CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, alpha_i)).unwrap();
+        let method_op = operation.call_method0(py, "alpha_i").unwrap();
+        let comparison_alpha_i = bool::extract(
+            method_op
+                .as_ref(py)
+                .call_method1("__eq__", (alpha_i_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_alpha_i);
+    })
 }
 
 /// Test beta_r obtained via the python interface for SingleQubitGate Operations
@@ -1573,23 +1566,23 @@ fn test_pyo3_alpha_i(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from(0.0))); "PhaseShiftState1")]
 fn test_pyo3_beta_r(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-
-    let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
-    let beta_r = gate.beta_r();
-    let beta_r_param: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, beta_r)).unwrap();
-    let method_op = operation.call_method0(py, "beta_r").unwrap();
-    let comparison_beta_r = bool::extract(
-        method_op
-            .as_ref(py)
-            .call_method1("__eq__", (beta_r_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_beta_r);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+
+        let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
+        let beta_r = gate.beta_r();
+        let beta_r_param: CalculatorFloatWrapper =
+            CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, beta_r)).unwrap();
+        let method_op = operation.call_method0(py, "beta_r").unwrap();
+        let comparison_beta_r = bool::extract(
+            method_op
+                .as_ref(py)
+                .call_method1("__eq__", (beta_r_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_beta_r);
+    })
 }
 
 /// Test beta_i obtained via the python interface for SingleQubitGate Operations
@@ -1628,23 +1621,23 @@ fn test_pyo3_beta_r(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from(0.0))); "PhaseShiftState1")]
 fn test_pyo3_beta_i(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-
-    let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
-    let beta_i = gate.beta_i();
-    let beta_i_param: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, beta_i)).unwrap();
-    let method_op = operation.call_method0(py, "beta_i").unwrap();
-    let comparison_beta_i = bool::extract(
-        method_op
-            .as_ref(py)
-            .call_method1("__eq__", (beta_i_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_beta_i);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+
+        let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
+        let beta_i = gate.beta_i();
+        let beta_i_param: CalculatorFloatWrapper =
+            CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, beta_i)).unwrap();
+        let method_op = operation.call_method0(py, "beta_i").unwrap();
+        let comparison_beta_i = bool::extract(
+            method_op
+                .as_ref(py)
+                .call_method1("__eq__", (beta_i_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_beta_i);
+    })
 }
 
 /// Test global_phase obtained via the python interface for SingleQubitGate Operations
@@ -1683,23 +1676,23 @@ fn test_pyo3_beta_i(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from(0.0))); "PhaseShiftState1")]
 fn test_pyo3_global_phase(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-
-    let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
-    let global_phase = gate.global_phase();
-    let global_phase_param: CalculatorFloatWrapper =
-        CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, global_phase)).unwrap();
-    let method_op = operation.call_method0(py, "global_phase").unwrap();
-    let comparison_global_phase = bool::extract(
-        method_op
-            .as_ref(py)
-            .call_method1("__eq__", (global_phase_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_global_phase);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+
+        let gate: SingleQubitGateOperation = input_operation.try_into().unwrap();
+        let global_phase = gate.global_phase();
+        let global_phase_param: CalculatorFloatWrapper =
+            CalculatorFloatWrapper::extract(convert_cf_to_pyobject(py, global_phase)).unwrap();
+        let method_op = operation.call_method0(py, "global_phase").unwrap();
+        let comparison_global_phase = bool::extract(
+            method_op
+                .as_ref(py)
+                .call_method1("__eq__", (global_phase_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_global_phase);
+    })
 }
 
 /// Test format and repr functions
@@ -1780,15 +1773,15 @@ fn test_pyo3_global_phase(input_operation: Operation) {
     "PhaseShiftState1")]
 fn test_pyo3_format_repr(format_repr: &str, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-    assert_eq!(format_op, format_repr);
-    let to_repr = operation.call_method0(py, "__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-    assert_eq!(repr_op, format_repr);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+        assert_eq!(format_op, format_repr);
+        let to_repr = operation.call_method0(py, "__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+        assert_eq!(repr_op, format_repr);
+    })
 }
 
 /// Test substitute_parameters() function for gates having multiple parameters
@@ -1814,32 +1807,32 @@ fn test_pyo3_format_repr(format_repr: &str, input_operation: Operation) {
 ]
 fn test_pyo3_substitute_parameters(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let mut substitution_dict_py: HashMap<&str, f64> = HashMap::new();
-    substitution_dict_py.insert("param", 1.0);
-    substitution_dict_py.insert("param2", 0.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict_py,))
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let mut substitution_dict_py: HashMap<&str, f64> = HashMap::new();
+        substitution_dict_py.insert("param", 1.0);
+        substitution_dict_py.insert("param2", 0.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict_py,))
+            .unwrap();
 
-    let mut substitution_dict: Calculator = Calculator::new();
-    substitution_dict.set_variable("param", 1.0);
-    substitution_dict.set_variable("param2", 0.0);
-    let substitute_param = input_operation
-        .substitute_parameters(&mut substitution_dict)
-        .unwrap();
-    let test_operation = convert_operation_to_pyobject(substitute_param).unwrap();
+        let mut substitution_dict: Calculator = Calculator::new();
+        substitution_dict.set_variable("param", 1.0);
+        substitution_dict.set_variable("param2", 0.0);
+        let substitute_param = input_operation
+            .substitute_parameters(&mut substitution_dict)
+            .unwrap();
+        let test_operation = convert_operation_to_pyobject(substitute_param).unwrap();
 
-    let comparison = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (test_operation.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        let comparison = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (test_operation.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 /// Test substitute_parameters() function for one parameter
@@ -1850,30 +1843,30 @@ fn test_pyo3_substitute_parameters(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from("theta"))); "PhaseShiftState1")]
 fn test_pyo3_substitute_params_rotate(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let mut substitution_dict_py: HashMap<&str, f64> = HashMap::new();
-    substitution_dict_py.insert("theta", 1.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict_py,))
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let mut substitution_dict_py: HashMap<&str, f64> = HashMap::new();
+        substitution_dict_py.insert("theta", 1.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict_py,))
+            .unwrap();
 
-    let mut substitution_dict: Calculator = Calculator::new();
-    substitution_dict.set_variable("theta", 1.0);
-    let substitute_param = input_operation
-        .substitute_parameters(&mut substitution_dict)
-        .unwrap();
-    let test_operation = convert_operation_to_pyobject(substitute_param).unwrap();
+        let mut substitution_dict: Calculator = Calculator::new();
+        substitution_dict.set_variable("theta", 1.0);
+        let substitute_param = input_operation
+            .substitute_parameters(&mut substitution_dict)
+            .unwrap();
+        let test_operation = convert_operation_to_pyobject(substitute_param).unwrap();
 
-    let comparison = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (test_operation.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        let comparison = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (test_operation.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 /// Test substitute_parameters() causing an error `None`
@@ -1904,13 +1897,13 @@ fn test_pyo3_substitute_params_rotate(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftState1::new(0, CalculatorFloat::from("theta"))); "PhaseShiftState1")]
 fn test_pyo3_substitute_params_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let substitution_dict: HashMap<&str, f64> = HashMap::new();
-    let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let substitution_dict: HashMap<&str, f64> = HashMap::new();
+        let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test substitute parameters function for SingleQubitGate Operations where it has no effect
@@ -1929,23 +1922,23 @@ fn test_pyo3_substitute_params_error(input_operation: Operation) {
 #[test_case(Operation::from(RotateY::new(0, CalculatorFloat::from(0))); "RotateY")]
 fn test_ineffective_substitute_parameters(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let mut substitution_dict_py: HashMap<&str, f64> = HashMap::new();
-    substitution_dict_py.insert("theta", 0.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict_py,))
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let mut substitution_dict_py: HashMap<&str, f64> = HashMap::new();
+        substitution_dict_py.insert("theta", 0.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict_py,))
+            .unwrap();
 
-    let comparison = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (operation,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        let comparison = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (operation,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 #[test_case(
@@ -1982,22 +1975,22 @@ fn test_ineffective_substitute_parameters(input_operation: Operation) {
     ); "Rotation")]
 fn test_pyo3_rotate_powercf(first_op: Operation, second_op: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(first_op).unwrap();
-
-    let power = convert_cf_to_pyobject(py, CalculatorFloat::from(1.5));
-    let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
-
-    let remapped_op = operation.call_method1(py, "powercf", (power,)).unwrap();
-    let comparison = bool::extract(
-        remapped_op
-            .call_method1(py, "__eq__", (comparison_op,))
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(first_op).unwrap();
+
+        let power = convert_cf_to_pyobject(py, CalculatorFloat::from(1.5));
+        let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
+
+        let remapped_op = operation.call_method1(py, "powercf", (power,)).unwrap();
+        let comparison = bool::extract(
+            remapped_op
+                .call_method1(py, "__eq__", (comparison_op,))
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 /// Test the __richcmp__ function
@@ -2081,32 +2074,32 @@ fn test_pyo3_rotate_powercf(first_op: Operation, second_op: Operation) {
     Operation::from(PhaseShiftState1::new(1, CalculatorFloat::from(0))); "PhaseShiftState1")]
 fn test_pyo3_richcmp(definition_1: Operation, definition_2: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
-    let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__eq__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(!comparison);
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__ne__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
+        let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__eq__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(!comparison);
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__ne__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
 
-    let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
+        assert!(comparison.is_err());
 
-    let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
+        assert!(comparison.is_err());
+    })
 }
diff --git a/qoqo/tests/integration/operations/two_qubit_gate_operations.rs b/qoqo/tests/integration/operations/two_qubit_gate_operations.rs
index 19c50332..0dee696a 100644
--- a/qoqo/tests/integration/operations/two_qubit_gate_operations.rs
+++ b/qoqo/tests/integration/operations/two_qubit_gate_operations.rs
@@ -14,6 +14,7 @@ use ndarray::Array2;
 use num_complex::Complex64;
 use numpy::PyArray2;
 use pyo3::prelude::*;
+use pyo3::Python;
 use qoqo::operations::convert_operation_to_pyobject;
 use qoqo::operations::{
     BogoliubovWrapper, CNOTWrapper, ComplexPMInteractionWrapper, ControlledPauliYWrapper,
@@ -76,16 +77,16 @@ fn convert_cf_to_pyobject(
 #[test_case(Operation::from(PhaseShiftedControlledZ::new(0, 1, CalculatorFloat::PI)); "PhaseShiftedControlledZ")]
 fn test_pyo3_is_not_parametrized(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    assert!(!bool::extract(
-        operation
-            .call_method0(py, "is_parametrized")
-            .unwrap()
-            .as_ref(py)
-    )
-    .unwrap());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        assert!(!bool::extract(
+            operation
+                .call_method0(py, "is_parametrized")
+                .unwrap()
+                .as_ref(py)
+        )
+        .unwrap());
+    })
 }
 
 /// Test tags() function for TwoQubitGate Operations
@@ -264,15 +265,15 @@ fn test_pyo3_is_not_parametrized(input_operation: Operation) {
     Operation::from(PhaseShiftedControlledZ::new(0, 1, CalculatorFloat::FRAC_PI_4)); "PhaseShiftedControlledZ")]
 fn test_pyo3_tags(tags: Vec<&str>, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let tags_op: Vec<String> =
-        Vec::<String>::extract(operation.call_method0(py, "tags").unwrap().as_ref(py)).unwrap();
-    assert_eq!(tags_op.len(), tags.len());
-    for i in 0..tags.len() {
-        assert_eq!(tags_op[i], tags[i]);
-    }
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let tags_op: Vec<String> =
+            Vec::<String>::extract(operation.call_method0(py, "tags").unwrap().as_ref(py)).unwrap();
+        assert_eq!(tags_op.len(), tags.len());
+        for i in 0..tags.len() {
+            assert_eq!(tags_op[i], tags[i]);
+        }
+    })
 }
 
 /// Test hqslang() function for TwoQubitGate Operations
@@ -302,12 +303,12 @@ fn test_pyo3_tags(tags: Vec<&str>, input_operation: Operation) {
 #[test_case("PhaseShiftedControlledZ", Operation::from(PhaseShiftedControlledZ::new(0, 1, CalculatorFloat::PI)); "PhaseShiftedControlledZ")]
 fn test_pyo3_hqslang(name: &'static str, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let name_op: String =
-        String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
-    assert_eq!(name_op, name.to_string());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let name_op: String =
+            String::extract(operation.call_method0(py, "hqslang").unwrap().as_ref(py)).unwrap();
+        assert_eq!(name_op, name.to_string());
+    })
 }
 
 /// Test remap_qubits() function for TwoQubitGate Operations
@@ -334,37 +335,37 @@ fn test_pyo3_hqslang(name: &'static str, input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftedControlledZ::new(0, 1, CalculatorFloat::PI)); "PhaseShiftedControlledZ")]
 fn test_pyo3_remapqubits(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-
-    // test initial qubits
-    let control: usize =
-        usize::extract(operation.call_method0(py, "control").unwrap().as_ref(py)).unwrap();
-    assert_eq!(control.clone(), 0);
-    let target: usize =
-        usize::extract(operation.call_method0(py, "target").unwrap().as_ref(py)).unwrap();
-    assert_eq!(target.clone(), 1);
-
-    // remap qubits
-    let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    qubit_mapping.insert(0, 2);
-    qubit_mapping.insert(1, 3);
-    let result = operation
-        .call_method1(py, "remap_qubits", (qubit_mapping,))
-        .unwrap();
-
-    // test re-mapped qubit
-    let control_new: usize =
-        usize::extract(result.call_method0(py, "control").unwrap().as_ref(py)).unwrap();
-    assert_eq!(control_new.clone(), 2);
-    let target_new: usize =
-        usize::extract(result.call_method0(py, "target").unwrap().as_ref(py)).unwrap();
-    assert_eq!(target_new.clone(), 3);
-
-    // test that initial and rempapped qubits are different
-    assert_ne!(control, control_new);
-    assert_ne!(target, target_new);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+
+        // test initial qubits
+        let control: usize =
+            usize::extract(operation.call_method0(py, "control").unwrap().as_ref(py)).unwrap();
+        assert_eq!(control.clone(), 0);
+        let target: usize =
+            usize::extract(operation.call_method0(py, "target").unwrap().as_ref(py)).unwrap();
+        assert_eq!(target.clone(), 1);
+
+        // remap qubits
+        let mut qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        qubit_mapping.insert(0, 2);
+        qubit_mapping.insert(1, 3);
+        let result = operation
+            .call_method1(py, "remap_qubits", (qubit_mapping,))
+            .unwrap();
+
+        // test re-mapped qubit
+        let control_new: usize =
+            usize::extract(result.call_method0(py, "control").unwrap().as_ref(py)).unwrap();
+        assert_eq!(control_new.clone(), 2);
+        let target_new: usize =
+            usize::extract(result.call_method0(py, "target").unwrap().as_ref(py)).unwrap();
+        assert_eq!(target_new.clone(), 3);
+
+        // test that initial and rempapped qubits are different
+        assert_ne!(control, control_new);
+        assert_ne!(target, target_new);
+    })
 }
 
 // test remap_qubits() function returning an error.
@@ -392,14 +393,14 @@ fn test_pyo3_remapqubits(input_operation: Operation) {
 fn test_pyo3_remapqubits_error(input_operation: Operation) {
     // preparation
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    // remap qubits
-    let qubit_mapping: HashMap<usize, usize> = HashMap::new();
-    let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        // remap qubits
+        let qubit_mapping: HashMap<usize, usize> = HashMap::new();
+        let result = operation.call_method1(py, "remap_qubits", (qubit_mapping,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test unitary_matrix() function for TwoQubitGate Operations for the error case
@@ -417,12 +418,12 @@ fn test_pyo3_remapqubits_error(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftedControlledZ::new(0, 1, CalculatorFloat::from("test"))); "PhaseShiftedControlledZ")]
 fn test_pyo3_unitarymatrix_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let py_result = operation.call_method0(py, "unitary_matrix");
-    let result_ref = py_result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let py_result = operation.call_method0(py, "unitary_matrix");
+        let result_ref = py_result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test unitary_matrix() function for TwoQubitGate Operations
@@ -449,21 +450,21 @@ fn test_pyo3_unitarymatrix_error(input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftedControlledZ::new(0, 1, CalculatorFloat::PI)); "PhaseShiftedControlledZ")]
 fn test_pyo3_unitarymatrix(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
-    let py_result = operation.call_method0(py, "unitary_matrix").unwrap();
-    let result_matrix = py_result
-        .cast_as::<PyArray2<Complex64>>(py)
-        .unwrap()
-        .to_owned_array();
-
-    // compare to reference matrix obtained in Rust directly (without passing to Python)
-    let gate: GateOperation = input_operation.try_into().unwrap();
-    let rust_matrix: Result<Array2<Complex64>, RoqoqoError> = gate.unitary_matrix();
-    let test_matrix: Array2<Complex64> = rust_matrix.unwrap();
-
-    assert_eq!(result_matrix, test_matrix);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation.clone()).unwrap();
+        let py_result = operation.call_method0(py, "unitary_matrix").unwrap();
+        let result_matrix = py_result
+            .cast_as::<PyArray2<Complex64>>(py)
+            .unwrap()
+            .to_owned_array();
+
+        // compare to reference matrix obtained in Rust directly (without passing to Python)
+        let gate: GateOperation = input_operation.try_into().unwrap();
+        let rust_matrix: Result<Array2<Complex64>, RoqoqoError> = gate.unitary_matrix();
+        let test_matrix: Array2<Complex64> = rust_matrix.unwrap();
+
+        assert_eq!(result_matrix, test_matrix);
+    })
 }
 
 /// Test format and repr functions
@@ -533,15 +534,15 @@ fn test_pyo3_unitarymatrix(input_operation: Operation) {
     Operation::from(PhaseShiftedControlledZ::new(0, 1, CalculatorFloat::PI)); "PhaseShiftedControlledZ")]
 fn test_pyo3_format_repr(format_repr: &str, input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
-    let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
-    let to_repr = operation.call_method0(py, "__repr__").unwrap();
-    let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
-    assert_eq!(format_op, format_repr);
-    assert_eq!(repr_op, format_repr);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let to_format = operation.call_method1(py, "__format__", ("",)).unwrap();
+        let format_op: &str = <&str>::extract(to_format.as_ref(py)).unwrap();
+        let to_repr = operation.call_method0(py, "__repr__").unwrap();
+        let repr_op: &str = <&str>::extract(to_repr.as_ref(py)).unwrap();
+        assert_eq!(format_op, format_repr);
+        assert_eq!(repr_op, format_repr);
+    })
 }
 
 /// Test copy and deepcopy functions
@@ -568,29 +569,29 @@ fn test_pyo3_format_repr(format_repr: &str, input_operation: Operation) {
 #[test_case(Operation::from(PhaseShiftedControlledZ::new(0, 1, CalculatorFloat::PI)); "PhaseShiftedControlledZ")]
 fn test_pyo3_copy_deepcopy(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let copy_op = operation.call_method0(py, "__copy__").unwrap();
-    let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
-    let copy_deepcopy_param = operation.clone();
-
-    let comparison_copy = bool::extract(
-        copy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-    let comparison_deepcopy = bool::extract(
-        deepcopy_op
-            .as_ref(py)
-            .call_method1("__eq__", (copy_deepcopy_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let copy_op = operation.call_method0(py, "__copy__").unwrap();
+        let deepcopy_op = operation.call_method1(py, "__deepcopy__", ("",)).unwrap();
+        let copy_deepcopy_param = operation.clone();
+
+        let comparison_copy = bool::extract(
+            copy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+        let comparison_deepcopy = bool::extract(
+            deepcopy_op
+                .as_ref(py)
+                .call_method1("__eq__", (copy_deepcopy_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 /// Test substitute_parameters function
@@ -659,24 +660,24 @@ fn test_pyo3_copy_deepcopy(input_operation: Operation) {
             "PhaseShiftedControlledZ")]
 fn test_pyo3_substitute_parameters(first_op: Operation, second_op: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(first_op).unwrap();
-    let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
-    substitution_dict.insert("test", 1.0);
-    let substitute_op = operation
-        .call_method1(py, "substitute_parameters", (substitution_dict,))
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(first_op).unwrap();
+        let mut substitution_dict: HashMap<&str, f64> = HashMap::new();
+        substitution_dict.insert("test", 1.0);
+        let substitute_op = operation
+            .call_method1(py, "substitute_parameters", (substitution_dict,))
+            .unwrap();
+        let substitute_param = convert_operation_to_pyobject(second_op).unwrap();
+
+        let comparison = bool::extract(
+            substitute_op
+                .as_ref(py)
+                .call_method1("__eq__", (substitute_param.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let substitute_param = convert_operation_to_pyobject(second_op).unwrap();
-
-    let comparison = bool::extract(
-        substitute_op
-            .as_ref(py)
-            .call_method1("__eq__", (substitute_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+        assert!(comparison);
+    })
 }
 
 /// Test substitute_parameters returning an error
@@ -705,13 +706,13 @@ fn test_pyo3_substitute_parameters(first_op: Operation, second_op: Operation) {
             "PhaseShiftedControlledZ")]
 fn test_pyo3_substitute_params_error(input_operation: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(input_operation).unwrap();
-    let substitution_dict: HashMap<&str, f64> = HashMap::new();
-    let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(input_operation).unwrap();
+        let substitution_dict: HashMap<&str, f64> = HashMap::new();
+        let result = operation.call_method1(py, "substitute_parameters", (substitution_dict,));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+    })
 }
 
 /// Test powercf function of TwoQubitGate Operations
@@ -732,22 +733,22 @@ fn test_pyo3_substitute_params_error(input_operation: Operation) {
             "GivensRotationLittleEndian")]
 fn test_pyo3_powercf(first_op: Operation, second_op: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(first_op).unwrap();
-
-    let power = convert_cf_to_pyobject(py, CalculatorFloat::from(1.5));
-    let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
-
-    let remapped_op = operation.call_method1(py, "powercf", (power,)).unwrap();
-    let comparison = bool::extract(
-        remapped_op
-            .call_method1(py, "__eq__", (comparison_op,))
-            .unwrap()
-            .as_ref(py),
-    )
-    .unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let operation = convert_operation_to_pyobject(first_op).unwrap();
+
+        let power = convert_cf_to_pyobject(py, CalculatorFloat::from(1.5));
+        let comparison_op = convert_operation_to_pyobject(second_op).unwrap();
+
+        let remapped_op = operation.call_method1(py, "powercf", (power,)).unwrap();
+        let comparison = bool::extract(
+            remapped_op
+                .call_method1(py, "__eq__", (comparison_op,))
+                .unwrap()
+                .as_ref(py),
+        )
+        .unwrap();
+        assert!(comparison);
+    })
 }
 
 /// Test new() function for CNOT
@@ -756,40 +757,40 @@ fn test_pyo3_powercf(first_op: Operation, second_op: Operation) {
 fn test_new_cnot(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<CNOTWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<CNOTWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<CNOTWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<CNOTWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<CNOTWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<CNOTWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<CNOTWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "CNOTWrapper { internal: CNOT { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<CNOTWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<CNOTWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<CNOTWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "CNOTWrapper { internal: CNOT { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for SWAP
@@ -798,40 +799,40 @@ fn test_new_cnot(input_operation: Operation, arguments: (u32, u32), method: &str
 fn test_new_swap(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<SWAPWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<SWAPWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<SWAPWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<SWAPWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<SWAPWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<SWAPWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<SWAPWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "SWAPWrapper { internal: SWAP { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<SWAPWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<SWAPWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<SWAPWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "SWAPWrapper { internal: SWAP { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for ISwap
@@ -840,40 +841,40 @@ fn test_new_swap(input_operation: Operation, arguments: (u32, u32), method: &str
 fn test_new_iswap(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<ISwapWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<ISwapWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<ISwapWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<ISwapWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<ISwapWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<ISwapWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<ISwapWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "ISwapWrapper { internal: ISwap { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<ISwapWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<ISwapWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<ISwapWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "ISwapWrapper { internal: ISwap { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for FSwap
@@ -882,40 +883,40 @@ fn test_new_iswap(input_operation: Operation, arguments: (u32, u32), method: &st
 fn test_new_fswap(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<FSwapWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<FSwapWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<FSwapWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<FSwapWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<FSwapWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<FSwapWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<FSwapWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "FSwapWrapper { internal: FSwap { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<FSwapWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<FSwapWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<FSwapWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "FSwapWrapper { internal: FSwap { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for SqrtISwap
@@ -924,40 +925,40 @@ fn test_new_fswap(input_operation: Operation, arguments: (u32, u32), method: &st
 fn test_new_sqrtiswap(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<SqrtISwapWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<SqrtISwapWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<SqrtISwapWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<SqrtISwapWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<SqrtISwapWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<SqrtISwapWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<SqrtISwapWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "SqrtISwapWrapper { internal: SqrtISwap { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<SqrtISwapWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<SqrtISwapWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<SqrtISwapWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "SqrtISwapWrapper { internal: SqrtISwap { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for InvSqrtISwap
@@ -966,40 +967,40 @@ fn test_new_sqrtiswap(input_operation: Operation, arguments: (u32, u32), method:
 fn test_new_invsqrtiswap(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<InvSqrtISwapWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<InvSqrtISwapWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<InvSqrtISwapWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<InvSqrtISwapWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<InvSqrtISwapWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<InvSqrtISwapWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<InvSqrtISwapWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "InvSqrtISwapWrapper { internal: InvSqrtISwap { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<InvSqrtISwapWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<InvSqrtISwapWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<InvSqrtISwapWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "InvSqrtISwapWrapper { internal: InvSqrtISwap { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for ControlledPauliY
@@ -1008,40 +1009,40 @@ fn test_new_invsqrtiswap(input_operation: Operation, arguments: (u32, u32), meth
 fn test_new_controlledpauliy(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<ControlledPauliYWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<ControlledPauliYWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<ControlledPauliYWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<ControlledPauliYWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<ControlledPauliYWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<ControlledPauliYWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<ControlledPauliYWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "ControlledPauliYWrapper { internal: ControlledPauliY { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<ControlledPauliYWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<ControlledPauliYWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<ControlledPauliYWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "ControlledPauliYWrapper { internal: ControlledPauliY { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for ControlledPauliZ
@@ -1050,40 +1051,40 @@ fn test_new_controlledpauliy(input_operation: Operation, arguments: (u32, u32),
 fn test_new_controlledpauliz(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<ControlledPauliZWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<ControlledPauliZWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<ControlledPauliZWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<ControlledPauliZWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<ControlledPauliZWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<ControlledPauliZWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<ControlledPauliZWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "ControlledPauliZWrapper { internal: ControlledPauliZ { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<ControlledPauliZWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<ControlledPauliZWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<ControlledPauliZWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "ControlledPauliZWrapper { internal: ControlledPauliZ { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for MolmerSorensenXX
@@ -1092,40 +1093,40 @@ fn test_new_controlledpauliz(input_operation: Operation, arguments: (u32, u32),
 fn test_new_molmersorensenxx(input_operation: Operation, arguments: (u32, u32), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_type = py.get_type::<MolmerSorensenXXWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<MolmerSorensenXXWrapper>>()
+    Python::with_gil(|py| -> () {
+        let operation_type = py.get_type::<MolmerSorensenXXWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<MolmerSorensenXXWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let def_wrapper = operation_py.extract::<MolmerSorensenXXWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2))
-        .unwrap()
-        .cast_as::<PyCell<MolmerSorensenXXWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<MolmerSorensenXXWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "MolmerSorensenXXWrapper { internal: MolmerSorensenXX { control: 1, target: 2 } }"
-    );
+        let def_wrapper = operation_py.extract::<MolmerSorensenXXWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2))
+            .unwrap()
+            .cast_as::<PyCell<MolmerSorensenXXWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<MolmerSorensenXXWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "MolmerSorensenXXWrapper { internal: MolmerSorensenXX { control: 1, target: 2 } }"
+        );
+    })
 }
 
 /// Test new() function for XY
@@ -1134,47 +1135,46 @@ fn test_new_molmersorensenxx(input_operation: Operation, arguments: (u32, u32),
 fn test_new_xy(input_operation: Operation, arguments: (u32, u32, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<XYWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<XYWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<XYWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<XYWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<XYWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<XYWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<XYWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "XYWrapper { internal: XY { control: 1, target: 2, theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<XYWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<XYWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<XYWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "XYWrapper { internal: XY { control: 1, target: 2, theta: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for ControlledPhaseShift
@@ -1187,51 +1187,50 @@ fn test_new_controlledphaseshift(
 ) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<ControlledPhaseShiftWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<ControlledPhaseShiftWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py
-        .extract::<ControlledPhaseShiftWrapper>()
-        .unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<ControlledPhaseShiftWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff
-        .extract::<ControlledPhaseShiftWrapper>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<ControlledPhaseShiftWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<ControlledPhaseShiftWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "ControlledPhaseShiftWrapper { internal: ControlledPhaseShift { control: 1, target: 2, theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py
+            .extract::<ControlledPhaseShiftWrapper>()
+            .unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<ControlledPhaseShiftWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff
+            .extract::<ControlledPhaseShiftWrapper>()
+            .unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "ControlledPhaseShiftWrapper { internal: ControlledPhaseShift { control: 1, target: 2, theta: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for VariableMSXX
@@ -1240,47 +1239,46 @@ fn test_new_controlledphaseshift(
 fn test_new_variablemsxx(input_operation: Operation, arguments: (u32, u32, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<VariableMSXXWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<VariableMSXXWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<VariableMSXXWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<VariableMSXXWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<VariableMSXXWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<VariableMSXXWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<VariableMSXXWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "VariableMSXXWrapper { internal: VariableMSXX { control: 1, target: 2, theta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<VariableMSXXWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<VariableMSXXWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<VariableMSXXWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "VariableMSXXWrapper { internal: VariableMSXX { control: 1, target: 2, theta: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for PMInteraction
@@ -1289,47 +1287,46 @@ fn test_new_variablemsxx(input_operation: Operation, arguments: (u32, u32, f64),
 fn test_new_pminteraction(input_operation: Operation, arguments: (u32, u32, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<PMInteractionWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<PMInteractionWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<PMInteractionWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<PMInteractionWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<PMInteractionWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<PMInteractionWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<PMInteractionWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "PMInteractionWrapper { internal: PMInteraction { control: 1, target: 2, t: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<PMInteractionWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<PMInteractionWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<PMInteractionWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "PMInteractionWrapper { internal: PMInteraction { control: 1, target: 2, t: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for GivensRotation
@@ -1342,51 +1339,50 @@ fn test_new_givensrotation(
 ) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<GivensRotationWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<GivensRotationWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<GivensRotationWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<GivensRotationWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<GivensRotationWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<GivensRotationWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<GivensRotationWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "GivensRotationWrapper { internal: GivensRotation { control: 1, target: 2, theta: Float(0.0), phi: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<GivensRotationWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<GivensRotationWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<GivensRotationWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "GivensRotationWrapper { internal: GivensRotation { control: 1, target: 2, theta: Float(0.0), phi: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for GivensRotationLittleEndian
@@ -1399,55 +1395,54 @@ fn test_new_givensrotationlittleendian(
 ) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<GivensRotationLittleEndianWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<GivensRotationLittleEndianWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py
-        .extract::<GivensRotationLittleEndianWrapper>()
-        .unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<GivensRotationLittleEndianWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff
-        .extract::<GivensRotationLittleEndianWrapper>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<GivensRotationLittleEndianWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<GivensRotationLittleEndianWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "GivensRotationLittleEndianWrapper { internal: GivensRotationLittleEndian { control: 1, target: 2, theta: Float(0.0), phi: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py
+            .extract::<GivensRotationLittleEndianWrapper>()
+            .unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<GivensRotationLittleEndianWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff
+            .extract::<GivensRotationLittleEndianWrapper>()
+            .unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "GivensRotationLittleEndianWrapper { internal: GivensRotationLittleEndian { control: 1, target: 2, theta: Float(0.0), phi: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for Bogoliubov
@@ -1456,51 +1451,50 @@ fn test_new_givensrotationlittleendian(
 fn test_new_bogoliubov(input_operation: Operation, arguments: (u32, u32, f64, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<BogoliubovWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<BogoliubovWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<BogoliubovWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<BogoliubovWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<BogoliubovWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<BogoliubovWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<BogoliubovWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "BogoliubovWrapper { internal: Bogoliubov { control: 1, target: 2, delta_real: Float(0.0), delta_imag: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<BogoliubovWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<BogoliubovWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<BogoliubovWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "BogoliubovWrapper { internal: Bogoliubov { control: 1, target: 2, delta_real: Float(0.0), delta_imag: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for ComplexPMInteraction
@@ -1513,55 +1507,54 @@ fn test_new_complexpminteraction(
 ) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<ComplexPMInteractionWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<ComplexPMInteractionWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py
-        .extract::<ComplexPMInteractionWrapper>()
-        .unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<ComplexPMInteractionWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff
-        .extract::<ComplexPMInteractionWrapper>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<ComplexPMInteractionWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<ComplexPMInteractionWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "ComplexPMInteractionWrapper { internal: ComplexPMInteraction { control: 1, target: 2, t_real: Float(0.0), t_imag: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py
+            .extract::<ComplexPMInteractionWrapper>()
+            .unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<ComplexPMInteractionWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff
+            .extract::<ComplexPMInteractionWrapper>()
+            .unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "ComplexPMInteractionWrapper { internal: ComplexPMInteraction { control: 1, target: 2, t_real: Float(0.0), t_imag: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for Qsim
@@ -1570,55 +1563,54 @@ fn test_new_complexpminteraction(
 fn test_new_qsim(input_operation: Operation, arguments: (u32, u32, f64, f64, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<QsimWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<QsimWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"], 0.0, 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<QsimWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<QsimWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<QsimWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<QsimWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<QsimWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "QsimWrapper { internal: Qsim { control: 1, target: 2, x: Float(0.0), y: Float(0.0), z: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"], 0.0, 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<QsimWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<QsimWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<QsimWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "QsimWrapper { internal: Qsim { control: 1, target: 2, x: Float(0.0), y: Float(0.0), z: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for Fsim
@@ -1627,55 +1619,54 @@ fn test_new_qsim(input_operation: Operation, arguments: (u32, u32, f64, f64, f64
 fn test_new_fsim(input_operation: Operation, arguments: (u32, u32, f64, f64, f64), method: &str) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<FsimWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<FsimWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"], 0.0, 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<FsimWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<FsimWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<FsimWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<FsimWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<FsimWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "FsimWrapper { internal: Fsim { control: 1, target: 2, t: Float(0.0), u: Float(0.0), delta: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"], 0.0, 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<FsimWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<FsimWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<FsimWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "FsimWrapper { internal: Fsim { control: 1, target: 2, t: Float(0.0), u: Float(0.0), delta: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for SpinInteraction
@@ -1688,56 +1679,55 @@ fn test_new_spininteraction(
 ) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<SpinInteractionWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<SpinInteractionWrapper>>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<SpinInteractionWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<SpinInteractionWrapper>>()
+            .unwrap();
+
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"], 0.0, 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, vec!["fails"], 0.0));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    let result = operation_type.call1((0, 1, 0.0, 0.0, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py.extract::<SpinInteractionWrapper>().unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0, 0.0, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<SpinInteractionWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff.extract::<SpinInteractionWrapper>().unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "SpinInteractionWrapper { internal: SpinInteraction { control: 1, target: 2, x: Float(0.0), y: Float(0.0), z: Float(0.0) } }"
-    );
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"], 0.0, 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, vec!["fails"], 0.0));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        let result = operation_type.call1((0, 1, 0.0, 0.0, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py.extract::<SpinInteractionWrapper>().unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0, 0.0, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<SpinInteractionWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff.extract::<SpinInteractionWrapper>().unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "SpinInteractionWrapper { internal: SpinInteraction { control: 1, target: 2, x: Float(0.0), y: Float(0.0), z: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test new() function for PhaseShiftedControlledZ
@@ -1750,51 +1740,50 @@ fn test_new_phaseshiftedcontrolledz(
 ) {
     let operation = convert_operation_to_pyobject(input_operation).unwrap();
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    // Basic initialisation, no errors
-    let operation_type = py.get_type::<PhaseShiftedControlledZWrapper>();
-    let operation_py = operation_type
-        .call1(arguments)
-        .unwrap()
-        .cast_as::<PyCell<PhaseShiftedControlledZWrapper>>()
-        .unwrap();
-    let comparison = bool::extract(
-        operation
-            .as_ref(py)
-            .call_method1(method, (operation_py,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    // Error initialisation
-    let result = operation_type.call1((0, 1, vec!["fails"]));
-    let result_ref = result.as_ref();
-    assert!(result_ref.is_err());
-
-    // Testing PartialEq, Clone and Debug
-    let def_wrapper = operation_py
-        .extract::<PhaseShiftedControlledZWrapper>()
-        .unwrap();
-    let new_op_diff = operation_type
-        .call1((1, 2, 0.0))
-        .unwrap()
-        .cast_as::<PyCell<PhaseShiftedControlledZWrapper>>()
-        .unwrap();
-    let def_wrapper_diff = new_op_diff
-        .extract::<PhaseShiftedControlledZWrapper>()
+    Python::with_gil(|py| -> () {
+        // Basic initialisation, no errors
+        let operation_type = py.get_type::<PhaseShiftedControlledZWrapper>();
+        let operation_py = operation_type
+            .call1(arguments)
+            .unwrap()
+            .cast_as::<PyCell<PhaseShiftedControlledZWrapper>>()
+            .unwrap();
+        let comparison = bool::extract(
+            operation
+                .as_ref(py)
+                .call_method1(method, (operation_py,))
+                .unwrap(),
+        )
         .unwrap();
-    let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
-    assert!(helper_ne);
-    let helper_eq: bool = def_wrapper == def_wrapper.clone();
-    assert!(helper_eq);
-
-    assert_eq!(
-        format!("{:?}", def_wrapper_diff),
-        "PhaseShiftedControlledZWrapper { internal: PhaseShiftedControlledZ { control: 1, target: 2, phi: Float(0.0) } }"
-    );
+        assert!(comparison);
+
+        // Error initialisation
+        let result = operation_type.call1((0, 1, vec!["fails"]));
+        let result_ref = result.as_ref();
+        assert!(result_ref.is_err());
+
+        // Testing PartialEq, Clone and Debug
+        let def_wrapper = operation_py
+            .extract::<PhaseShiftedControlledZWrapper>()
+            .unwrap();
+        let new_op_diff = operation_type
+            .call1((1, 2, 0.0))
+            .unwrap()
+            .cast_as::<PyCell<PhaseShiftedControlledZWrapper>>()
+            .unwrap();
+        let def_wrapper_diff = new_op_diff
+            .extract::<PhaseShiftedControlledZWrapper>()
+            .unwrap();
+        let helper_ne: bool = def_wrapper_diff != def_wrapper.clone();
+        assert!(helper_ne);
+        let helper_eq: bool = def_wrapper == def_wrapper.clone();
+        assert!(helper_eq);
+
+        assert_eq!(
+            format!("{:?}", def_wrapper_diff),
+            "PhaseShiftedControlledZWrapper { internal: PhaseShiftedControlledZ { control: 1, target: 2, phi: Float(0.0) } }"
+        );
+    })
 }
 
 /// Test the __richcmp__ function
@@ -1863,32 +1852,32 @@ fn test_new_phaseshiftedcontrolledz(
     Operation::from(PhaseShiftedControlledZ::new(1, 0, CalculatorFloat::PI)); "PhaseShiftedControlledZ")]
 fn test_pyo3_richcmp(definition_1: Operation, definition_2: Operation) {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
-    let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__eq__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(!comparison);
-
-    let comparison = bool::extract(
-        operation_one
-            .as_ref(py)
-            .call_method1("__ne__", (operation_two.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
+    Python::with_gil(|py| -> () {
+        let operation_one = convert_operation_to_pyobject(definition_1).unwrap();
+        let operation_two = convert_operation_to_pyobject(definition_2).unwrap();
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__eq__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(!comparison);
+
+        let comparison = bool::extract(
+            operation_one
+                .as_ref(py)
+                .call_method1("__ne__", (operation_two.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison);
 
-    let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__eq__", (vec!["fails"],));
+        assert!(comparison.is_err());
 
-    let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
-    assert!(comparison.is_err());
+        let comparison = operation_one.call_method1(py, "__ge__", (operation_two,));
+        assert!(comparison.is_err());
+    })
 }
diff --git a/qoqo/tests/integration/quantum_program.rs b/qoqo/tests/integration/quantum_program.rs
index 07dc3c2a..796bdb07 100644
--- a/qoqo/tests/integration/quantum_program.rs
+++ b/qoqo/tests/integration/quantum_program.rs
@@ -63,6 +63,7 @@ fn create_measurement(py: Python) -> &PyCell<CheatedBasisRotationWrapper> {
 /// Test basic traits of QuantumProgramWrapper
 #[test]
 fn test_basic_traits() {
+    pyo3::prepare_freethreaded_python();
     Python::with_gil(|py| -> () {
         let input = create_measurement(py);
         let program_type = py.get_type::<QuantumProgramWrapper>();
@@ -94,509 +95,497 @@ fn test_basic_traits() {
 #[test]
 fn test_new_run_br() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<BasisRotationInputWrapper>();
+        let input_instance = input_type
+            .call1((3, false))
+            .unwrap()
+            .cast_as::<PyCell<BasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input_instance
+            .call_method1("add_pauli_product", ("ro", vec![0]))
+            .unwrap();
 
-    let input_type = py.get_type::<BasisRotationInputWrapper>();
-    let input_instance = input_type
-        .call1((3, false))
-        .unwrap()
-        .cast_as::<PyCell<BasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input_instance
-        .call_method1("add_pauli_product", ("ro", vec![0]))
-        .unwrap();
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += RotateX::new(0, 0.0.into());
+        circs.push(circ1.clone());
+        let br_type = py.get_type::<BasisRotationWrapper>();
+        let input = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input_instance))
+            .unwrap()
+            .cast_as::<PyCell<BasisRotationWrapper>>()
+            .unwrap();
 
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += RotateX::new(0, 0.0.into());
-    circs.push(circ1.clone());
-    let br_type = py.get_type::<BasisRotationWrapper>();
-    let input = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input_instance))
-        .unwrap()
-        .cast_as::<PyCell<BasisRotationWrapper>>()
-        .unwrap();
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let program_wrapper = program.extract::<QuantumProgramWrapper>().unwrap();
 
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
-    let program_wrapper = program.extract::<QuantumProgramWrapper>().unwrap();
-
-    let mut bri = BasisRotationInput::new(3, false);
-    let _ = bri.add_pauli_product("ro".to_string(), vec![0]);
-    let br = BasisRotation {
-        constant_circuit: Some(Circuit::new()),
-        circuits: vec![Circuit::new(), circ1.internal],
-        input: bri,
-    };
-
-    assert_eq!(
-        program_wrapper,
-        QuantumProgramWrapper {
-            internal: QuantumProgram::BasisRotation {
-                measurement: br.clone(),
-                input_parameter_names: vec!["test".to_string()]
+        let mut bri = BasisRotationInput::new(3, false);
+        let _ = bri.add_pauli_product("ro".to_string(), vec![0]);
+        let br = BasisRotation {
+            constant_circuit: Some(Circuit::new()),
+            circuits: vec![Circuit::new(), circ1.internal],
+            input: bri,
+        };
+
+        assert_eq!(
+            program_wrapper,
+            QuantumProgramWrapper {
+                internal: QuantumProgram::BasisRotation {
+                    measurement: br.clone(),
+                    input_parameter_names: vec!["test".to_string()]
+                }
             }
-        }
-    );
-
-    let measurement = BasisRotationWrapper::extract(
-        program
-            .call_method1("run", (TestBackend, Some(vec![0.0])))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(measurement.internal, br);
+        );
+
+        let measurement = BasisRotationWrapper::extract(
+            program
+                .call_method1("run", (TestBackend, Some(vec![0.0])))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(measurement.internal, br);
+    })
 }
 
 /// Test new and run functions of QuantumProgram with all CheatedBasisRotation measurement input
 #[test]
 fn test_new_run_cheated_br() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
+        let input_instance = input_type
+            .call0()
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
+            .unwrap();
+        let _ = input_instance
+            .call_method1("add_pauli_product", ("ro",))
+            .unwrap();
 
-    let input_type = py.get_type::<CheatedBasisRotationInputWrapper>();
-    let input_instance = input_type
-        .call0()
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationInputWrapper>>()
-        .unwrap();
-    let _ = input_instance
-        .call_method1("add_pauli_product", ("ro",))
-        .unwrap();
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += RotateX::new(0, 0.0.into());
+        circs.push(circ1.clone());
+        let br_type = py.get_type::<CheatedBasisRotationWrapper>();
+        let input = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input_instance))
+            .unwrap()
+            .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
+            .unwrap();
 
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += RotateX::new(0, 0.0.into());
-    circs.push(circ1.clone());
-    let br_type = py.get_type::<CheatedBasisRotationWrapper>();
-    let input = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input_instance))
-        .unwrap()
-        .cast_as::<PyCell<CheatedBasisRotationWrapper>>()
-        .unwrap();
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let program_wrapper = program.extract::<QuantumProgramWrapper>().unwrap();
 
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
-    let program_wrapper = program.extract::<QuantumProgramWrapper>().unwrap();
-
-    let mut cbri = CheatedBasisRotationInput::new();
-    cbri.add_pauli_product("ro".to_string());
-    let cbr = CheatedBasisRotation {
-        constant_circuit: Some(Circuit::new()),
-        circuits: vec![Circuit::new(), circ1.internal],
-        input: cbri,
-    };
-
-    assert_eq!(
-        program_wrapper,
-        QuantumProgramWrapper {
-            internal: QuantumProgram::CheatedBasisRotation {
-                measurement: cbr.clone(),
-                input_parameter_names: vec!["test".to_string()]
+        let mut cbri = CheatedBasisRotationInput::new();
+        cbri.add_pauli_product("ro".to_string());
+        let cbr = CheatedBasisRotation {
+            constant_circuit: Some(Circuit::new()),
+            circuits: vec![Circuit::new(), circ1.internal],
+            input: cbri,
+        };
+
+        assert_eq!(
+            program_wrapper,
+            QuantumProgramWrapper {
+                internal: QuantumProgram::CheatedBasisRotation {
+                    measurement: cbr.clone(),
+                    input_parameter_names: vec!["test".to_string()]
+                }
             }
-        }
-    );
-
-    let measurement = CheatedBasisRotationWrapper::extract(
-        program
-            .call_method1("run", (TestBackend, Some(vec![0.0])))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(measurement.internal, cbr);
-    let error = program.call_method1("run_registers", (TestBackend, Some(vec![0.0])));
-    assert!(error.is_err());
+        );
+
+        let measurement = CheatedBasisRotationWrapper::extract(
+            program
+                .call_method1("run", (TestBackend, Some(vec![0.0])))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(measurement.internal, cbr);
+        let error = program.call_method1("run_registers", (TestBackend, Some(vec![0.0])));
+        assert!(error.is_err());
+    })
 }
 
 /// Test new and run functions of QuantumProgram with all Cheated measurement input
 #[test]
 fn test_new_run_cheated() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
+    Python::with_gil(|py| -> () {
+        let input_type = py.get_type::<CheatedInputWrapper>();
+        let input_instance = input_type
+            .call1((2,))
+            .unwrap()
+            .cast_as::<PyCell<CheatedInputWrapper>>()
+            .unwrap();
 
-    let input_type = py.get_type::<CheatedInputWrapper>();
-    let input_instance = input_type
-        .call1((2,))
-        .unwrap()
-        .cast_as::<PyCell<CheatedInputWrapper>>()
-        .unwrap();
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += RotateX::new(0, 0.0.into());
+        circs.push(circ1.clone());
+        let br_type = py.get_type::<CheatedWrapper>();
+        let input = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone(), input_instance))
+            .unwrap()
+            .cast_as::<PyCell<CheatedWrapper>>()
+            .unwrap();
 
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += RotateX::new(0, 0.0.into());
-    circs.push(circ1.clone());
-    let br_type = py.get_type::<CheatedWrapper>();
-    let input = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone(), input_instance))
-        .unwrap()
-        .cast_as::<PyCell<CheatedWrapper>>()
-        .unwrap();
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let program_wrapper = program.extract::<QuantumProgramWrapper>().unwrap();
 
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
-    let program_wrapper = program.extract::<QuantumProgramWrapper>().unwrap();
-
-    let ci = CheatedInput::new(2);
-    let cheated = Cheated {
-        constant_circuit: Some(Circuit::new()),
-        circuits: vec![Circuit::new(), circ1.internal],
-        input: ci,
-    };
-
-    assert_eq!(
-        program_wrapper,
-        QuantumProgramWrapper {
-            internal: QuantumProgram::Cheated {
-                measurement: cheated.clone(),
-                input_parameter_names: vec!["test".to_string()]
+        let ci = CheatedInput::new(2);
+        let cheated = Cheated {
+            constant_circuit: Some(Circuit::new()),
+            circuits: vec![Circuit::new(), circ1.internal],
+            input: ci,
+        };
+
+        assert_eq!(
+            program_wrapper,
+            QuantumProgramWrapper {
+                internal: QuantumProgram::Cheated {
+                    measurement: cheated.clone(),
+                    input_parameter_names: vec!["test".to_string()]
+                }
             }
-        }
-    );
-
-    let measurement = CheatedWrapper::extract(
-        program
-            .call_method1("run", (TestBackend, Some(vec![0.0])))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(measurement.internal, cheated);
+        );
+
+        let measurement = CheatedWrapper::extract(
+            program
+                .call_method1("run", (TestBackend, Some(vec![0.0])))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(measurement.internal, cheated);
+    })
 }
 
 /// Test new and run_register functions of QuantumProgram with all ClassicalRegister measurement input
 #[test]
 fn test_new_run_classical_register() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
+    Python::with_gil(|py| -> () {
+        let mut circs: Vec<CircuitWrapper> = Vec::new();
+        circs.push(CircuitWrapper::new());
+        let mut circ1 = CircuitWrapper::new();
+        circ1.internal += RotateX::new(0, 0.0.into());
+        circs.push(circ1.clone());
+        let br_type = py.get_type::<ClassicalRegisterWrapper>();
+        let input = br_type
+            .call1((Some(CircuitWrapper::new()), circs.clone()))
+            .unwrap()
+            .cast_as::<PyCell<ClassicalRegisterWrapper>>()
+            .unwrap();
 
-    let mut circs: Vec<CircuitWrapper> = Vec::new();
-    circs.push(CircuitWrapper::new());
-    let mut circ1 = CircuitWrapper::new();
-    circ1.internal += RotateX::new(0, 0.0.into());
-    circs.push(circ1.clone());
-    let br_type = py.get_type::<ClassicalRegisterWrapper>();
-    let input = br_type
-        .call1((Some(CircuitWrapper::new()), circs.clone()))
-        .unwrap()
-        .cast_as::<PyCell<ClassicalRegisterWrapper>>()
-        .unwrap();
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let program_wrapper = program.extract::<QuantumProgramWrapper>().unwrap();
 
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
-    let program_wrapper = program.extract::<QuantumProgramWrapper>().unwrap();
-
-    let cr = ClassicalRegister {
-        constant_circuit: Some(Circuit::new()),
-        circuits: vec![Circuit::new(), circ1.internal],
-    };
-
-    assert_eq!(
-        program_wrapper,
-        QuantumProgramWrapper {
-            internal: QuantumProgram::ClassicalRegister {
-                measurement: cr.clone(),
-                input_parameter_names: vec!["test".to_string()]
+        let cr = ClassicalRegister {
+            constant_circuit: Some(Circuit::new()),
+            circuits: vec![Circuit::new(), circ1.internal],
+        };
+
+        assert_eq!(
+            program_wrapper,
+            QuantumProgramWrapper {
+                internal: QuantumProgram::ClassicalRegister {
+                    measurement: cr.clone(),
+                    input_parameter_names: vec!["test".to_string()]
+                }
             }
-        }
-    );
-
-    let measurement = ClassicalRegisterWrapper::extract(
-        program
-            .call_method1("run_registers", (TestBackend, Some(vec![0.0])))
-            .unwrap(),
-    )
-    .unwrap();
-    assert_eq!(measurement.internal, cr);
-    let error = program.call_method1("run", (TestBackend, Some(vec![0.0])));
-    assert!(error.is_err());
+        );
+
+        let measurement = ClassicalRegisterWrapper::extract(
+            program
+                .call_method1("run_registers", (TestBackend, Some(vec![0.0])))
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(measurement.internal, cr);
+        let error = program.call_method1("run", (TestBackend, Some(vec![0.0])));
+        assert!(error.is_err());
+    })
 }
 
 /// Test new function of QuantumProgram first error
 #[test]
 fn test_new_error_1() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-
-    let circs: Vec<CircuitWrapper> = Vec::new();
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type.call1((circs, vec!["test".to_string()]));
-    assert!(program.is_err());
+    Python::with_gil(|py| -> () {
+        let circs: Vec<CircuitWrapper> = Vec::new();
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type.call1((circs, vec!["test".to_string()]));
+        assert!(program.is_err());
+    })
 }
 
 /// Test copy and deepcopy functions of QuantumProgram
 #[test]
 fn test_copy_deepcopy() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let input = create_measurement(py);
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let input = create_measurement(py);
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+
+        let copy_circ = program.call_method0("__copy__").unwrap();
+        let deepcopy_circ = program.call_method1("__deepcopy__", ("",)).unwrap();
+        let copy_deepcopy_param = program.clone();
 
-    let copy_circ = program.call_method0("__copy__").unwrap();
-    let deepcopy_circ = program.call_method1("__deepcopy__", ("",)).unwrap();
-    let copy_deepcopy_param = program.clone();
-
-    let comparison_copy = bool::extract(
-        copy_circ
-            .call_method1("__eq__", (copy_deepcopy_param.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_copy);
-    let comparison_deepcopy = bool::extract(
-        deepcopy_circ
-            .call_method1("__eq__", (copy_deepcopy_param,))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison_deepcopy);
+        let comparison_copy = bool::extract(
+            copy_circ
+                .call_method1("__eq__", (copy_deepcopy_param.clone(),))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_copy);
+        let comparison_deepcopy = bool::extract(
+            deepcopy_circ
+                .call_method1("__eq__", (copy_deepcopy_param,))
+                .unwrap(),
+        )
+        .unwrap();
+        assert!(comparison_deepcopy);
+    })
 }
 
 /// Test qoqo_versions function of QuantumProgram
 #[test]
 fn test_qoqo_versions() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let input = create_measurement(py);
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let input = create_measurement(py);
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+
+        let mut rsplit = ROQOQO_VERSION.split('.').take(2);
+        let mut qsplit = QOQO_VERSION.split('.').take(2);
+        let rver = format!(
+            "{}.{}",
+            rsplit.next().expect("ROQOQO_VERSION badly formatted"),
+            rsplit.next().expect("ROQOQO_VERSION badly formatted")
+        );
+        let qver = format!(
+            "{}.{}",
+            qsplit.next().expect("QOQO_VERSION badly formatted"),
+            qsplit.next().expect("QOQO_VERSION badly formatted")
+        );
 
-    let mut rsplit = ROQOQO_VERSION.split('.').take(2);
-    let mut qsplit = QOQO_VERSION.split('.').take(2);
-    let rver = format!(
-        "{}.{}",
-        rsplit.next().expect("ROQOQO_VERSION badly formatted"),
-        rsplit.next().expect("ROQOQO_VERSION badly formatted")
-    );
-    let qver = format!(
-        "{}.{}",
-        qsplit.next().expect("QOQO_VERSION badly formatted"),
-        qsplit.next().expect("QOQO_VERSION badly formatted")
-    );
-
-    let comparison_copy: Vec<&str> =
-        Vec::extract(program.call_method0("_qoqo_versions").unwrap()).unwrap();
-    assert_eq!(comparison_copy, vec![rver.as_str(), qver.as_str()]);
+        let comparison_copy: Vec<&str> =
+            Vec::extract(program.call_method0("_qoqo_versions").unwrap()).unwrap();
+        assert_eq!(comparison_copy, vec![rver.as_str(), qver.as_str()]);
+    })
 }
 
 /// Test to_ and from_bincode functions of QuantumProgram
 #[test]
 fn test_to_from_bincode() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let input = create_measurement(py);
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let input = create_measurement(py);
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
 
-    let serialised = program.call_method0("to_bincode").unwrap();
-    let new = program_type
-        .call1((input, vec!["new".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
-    let deserialised = new.call_method1("from_bincode", (serialised,)).unwrap();
+        let serialised = program.call_method0("to_bincode").unwrap();
+        let new = program_type
+            .call1((input, vec!["new".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let deserialised = new.call_method1("from_bincode", (serialised,)).unwrap();
 
-    let deserialised_error =
-        new.call_method1("from_bincode", (bincode::serialize("fails").unwrap(),));
-    assert!(deserialised_error.is_err());
+        let deserialised_error =
+            new.call_method1("from_bincode", (bincode::serialize("fails").unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let deserialised_error =
-        new.call_method1("from_bincode", (bincode::serialize(&vec![0]).unwrap(),));
-    assert!(deserialised_error.is_err());
+        let deserialised_error =
+            new.call_method1("from_bincode", (bincode::serialize(&vec![0]).unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let deserialised_error = deserialised.call_method0("from_bincode");
-    assert!(deserialised_error.is_err());
+        let deserialised_error = deserialised.call_method0("from_bincode");
+        assert!(deserialised_error.is_err());
 
-    let serialised_error = serialised.call_method0("to_bincode");
-    assert!(serialised_error.is_err());
+        let serialised_error = serialised.call_method0("to_bincode");
+        assert!(serialised_error.is_err());
 
-    let comparison =
-        bool::extract(deserialised.call_method1("__eq__", (program,)).unwrap()).unwrap();
-    assert!(comparison)
+        let comparison =
+            bool::extract(deserialised.call_method1("__eq__", (program,)).unwrap()).unwrap();
+        assert!(comparison)
+    })
 }
 
 #[test]
 fn test_value_error_bincode() {
     pyo3::prepare_freethreaded_python();
-    let gil = Python::acquire_gil();
-    let py = gil.python();
-    let input = create_measurement(py);
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let input = create_measurement(py);
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
 
-    let program_clone = program.clone();
-    let serialised = program.call_method0("to_bincode").unwrap();
-    let deserialised = program_clone
-        .call_method1("from_bincode", (serialised,))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
+        let program_clone = program.clone();
+        let serialised = program.call_method0("to_bincode").unwrap();
+        let deserialised = program_clone
+            .call_method1("from_bincode", (serialised,))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
 
-    let new = program_type
-        .call1((input, vec!["new".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
-    let deserialised_error = new.call_method1("from_bincode", (deserialised,));
-    assert!(deserialised_error.is_err());
+        let new = program_type
+            .call1((input, vec!["new".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let deserialised_error = new.call_method1("from_bincode", (deserialised,));
+        assert!(deserialised_error.is_err());
+    })
 }
 
 /// Test to_ and from_json functions of QuantumProgram
 #[test]
 fn test_to_from_json() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let input = create_measurement(py);
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["test".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
+    Python::with_gil(|py| -> () {
+        let input = create_measurement(py);
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["test".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
 
-    let serialised = program.call_method0("to_json").unwrap();
-    let new = program_type
-        .call1((input, vec!["new".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
-    let deserialised = new.call_method1("from_json", (serialised,)).unwrap();
+        let serialised = program.call_method0("to_json").unwrap();
+        let new = program_type
+            .call1((input, vec!["new".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let deserialised = new.call_method1("from_json", (serialised,)).unwrap();
 
-    let deserialised_error =
-        new.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
-    assert!(deserialised_error.is_err());
+        let deserialised_error =
+            new.call_method1("from_json", (serde_json::to_string("fails").unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let deserialised_error =
-        new.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
-    assert!(deserialised_error.is_err());
+        let deserialised_error =
+            new.call_method1("from_json", (serde_json::to_string(&vec![0]).unwrap(),));
+        assert!(deserialised_error.is_err());
 
-    let serialised_error = serialised.call_method0("to_json");
-    assert!(serialised_error.is_err());
+        let serialised_error = serialised.call_method0("to_json");
+        assert!(serialised_error.is_err());
 
-    let deserialised_error = deserialised.call_method0("from_json");
-    assert!(deserialised_error.is_err());
+        let deserialised_error = deserialised.call_method0("from_json");
+        assert!(deserialised_error.is_err());
 
-    let comparison =
-        bool::extract(deserialised.call_method1("__eq__", (program,)).unwrap()).unwrap();
-    assert!(comparison)
+        let comparison =
+            bool::extract(deserialised.call_method1("__eq__", (program,)).unwrap()).unwrap();
+        assert!(comparison)
+    })
 }
 
 /// Test the __richcmp__ function
 #[test]
 fn test_richcmp() {
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let input = create_measurement(py);
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program_one = program_type
-        .call1((input, vec!["one".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
+    Python::with_gil(|py| -> () {
+        let input = create_measurement(py);
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program_one = program_type
+            .call1((input, vec!["one".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let program_two = program_type
+            .call1((input, vec!["two".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+
+        let operation1 = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
+
+        let comparison =
+            bool::extract(program_one.call_method1("__eq__", (program_two,)).unwrap()).unwrap();
+        assert!(!comparison);
+        let comparison = bool::extract(
+            program_one
+                .call_method1("__eq__", (operation1.clone(),))
+                .unwrap(),
+        )
         .unwrap();
-    let program_two = program_type
-        .call1((input, vec!["two".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
+        assert!(!comparison);
+
+        let comparison =
+            bool::extract(program_one.call_method1("__ne__", (program_two,)).unwrap()).unwrap();
+        assert!(comparison);
+        let comparison = bool::extract(
+            program_one
+                .call_method1("__ne__", (operation1.clone(),))
+                .unwrap(),
+        )
         .unwrap();
+        assert!(comparison);
 
-    let operation1 = convert_operation_to_pyobject(Operation::from(PauliX::new(0))).unwrap();
-
-    let comparison =
-        bool::extract(program_one.call_method1("__eq__", (program_two,)).unwrap()).unwrap();
-    assert!(!comparison);
-    let comparison = bool::extract(
-        program_one
-            .call_method1("__eq__", (operation1.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(!comparison);
-
-    let comparison =
-        bool::extract(program_one.call_method1("__ne__", (program_two,)).unwrap()).unwrap();
-    assert!(comparison);
-    let comparison = bool::extract(
-        program_one
-            .call_method1("__ne__", (operation1.clone(),))
-            .unwrap(),
-    )
-    .unwrap();
-    assert!(comparison);
-
-    let comparison = program_one.call_method1("__ge__", (operation1,));
-    assert!(comparison.is_err());
+        let comparison = program_one.call_method1("__ge__", (operation1,));
+        assert!(comparison.is_err());
+    })
 }
 
 #[test]
 fn test_convert_into_program() {
-    let added_op = Operation::from(PauliX::new(0));
     pyo3::prepare_freethreaded_python();
-    let gil = pyo3::Python::acquire_gil();
-    let py = gil.python();
-    let operation = convert_operation_to_pyobject(added_op).unwrap();
-    // let circuit_type = py.get_type::<CircuitWrapper>();
-    // let circ = circuit_type
-    //     .call0()
-    //     .unwrap()
-    //     .cast_as::<PyCell<CircuitWrapper>>()
-    //     .unwrap();
-
-    let input = create_measurement(py);
-    let program_type = py.get_type::<QuantumProgramWrapper>();
-    let program = program_type
-        .call1((input, vec!["one".to_string()]))
-        .unwrap()
-        .cast_as::<PyCell<QuantumProgramWrapper>>()
-        .unwrap();
-    let comparison = program.call_method1("convert_into_quantum_program", (operation.clone(),));
-    assert!(comparison.is_err());
-    assert_eq!(
-        convert_into_quantum_program(operation.as_ref(py)),
-        Err(QoqoError::CannotExtractObject)
-    );
-    // assert_eq!(convert_into_quantum_program(circ), Err(QoqoError::VersionMismatch));
+    Python::with_gil(|py| -> () {
+        let added_op = Operation::from(PauliX::new(0));
+        let operation = convert_operation_to_pyobject(added_op).unwrap();
+        let input = create_measurement(py);
+        let program_type = py.get_type::<QuantumProgramWrapper>();
+        let program = program_type
+            .call1((input, vec!["one".to_string()]))
+            .unwrap()
+            .cast_as::<PyCell<QuantumProgramWrapper>>()
+            .unwrap();
+        let comparison = program.call_method1("convert_into_quantum_program", (operation.clone(),));
+        assert!(comparison.is_err());
+        assert_eq!(
+            convert_into_quantum_program(operation.as_ref(py)),
+            Err(QoqoError::CannotExtractObject)
+        );
+        // assert_eq!(convert_into_quantum_program(circ), Err(QoqoError::VersionMismatch));
+    })
 }
diff --git a/roqoqo/tests/integration/operations/single_qubit_gate_operations.rs b/roqoqo/tests/integration/operations/single_qubit_gate_operations.rs
index 8e2cb148..5f53bfd9 100644
--- a/roqoqo/tests/integration/operations/single_qubit_gate_operations.rs
+++ b/roqoqo/tests/integration/operations/single_qubit_gate_operations.rs
@@ -974,16 +974,23 @@ fn test_rotatez_substitute_parameters() {
 }
 
 /// Test substitute_parameters for PhaseShiftState0
-#[test]
-fn test_phaseshiftstate0_substitute_parameters() {
-    let gate: PhaseShiftState0 = PhaseShiftState0::new(0, CalculatorFloat::from("theta"));
-    assert_eq!(gate.theta().clone(), CalculatorFloat::from("theta"));
-    assert!(gate.is_parametrized());
+// #[test]
+#[test_case(
+    SingleQubitGateOperation::from(PhaseShiftState0::new(0, CalculatorFloat::from("theta"))),
+    SingleQubitGateOperation::from(PhaseShiftState0::new(0, CalculatorFloat::from(0.0))); "state0"
+)]
+fn test_phaseshiftstate0_substitute_parameters(
+    gate: SingleQubitGateOperation,
+    testgate: SingleQubitGateOperation,
+) {
+    // let gate: PhaseShiftState0 = PhaseShiftState0::new(0, CalculatorFloat::from("theta"));
+    // assert_eq!(gate.theta().clone(), CalculatorFloat::from("theta"));
+    // assert!(gate.is_parametrized());
     let mut substitution_dict: Calculator = Calculator::new();
     substitution_dict.set_variable("theta", 0.0);
     let result = gate.substitute_parameters(&mut substitution_dict).unwrap();
-    assert!(!result.is_parametrized());
-    assert_eq!(result.theta().clone(), CalculatorFloat::from(0.0));
+    // assert!(!result.is_parametrized());
+    assert_eq!(result, testgate);
 }
 
 /// Test substitute_parameters for PhaseShiftState1