Skip to content

Commit d797114

Browse files
committed
chore: use new Bound API
1 parent f5ea3e0 commit d797114

File tree

8 files changed

+76
-64
lines changed

8 files changed

+76
-64
lines changed

packages/cubejs-backend-native/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ log-reroute = "0.1"
3434
minijinja = { version = "1", features = ["json", "loader"] }
3535
once_cell = "1.10"
3636
# python
37-
pyo3 = { version = "0.22.6", features = ["gil-refs", "py-clone"], optional = true }
37+
pyo3 = { version = "0.22.6", features = ["py-clone"], optional = true }
3838
pyo3-async-runtimes = { version = "0.22.0", features = ["tokio-runtime", "attributes"], optional = true }
3939
serde = { version = "1.0.217", features = ["derive"] }
4040
serde_json = "1.0.127"

packages/cubejs-backend-native/src/cross/clrepr_python.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ use crate::cross::clrepr::CLReprObject;
22
use crate::cross::{CLRepr, CLReprObjectKind, StringType};
33
use pyo3::exceptions::{PyNotImplementedError, PyTypeError};
44
use pyo3::types::{
5-
PyBool, PyComplex, PyDate, PyDict, PyFloat, PyFrame, PyFunction, PyInt, PyList, PySequence,
6-
PySet, PyString, PyTraceback, PyTuple,
5+
PyAnyMethods, PyBool, PyBoolMethods, PyComplex, PyDate, PyDict, PyDictMethods, PyFloat,
6+
PyFloatMethods, PyFrame, PyFunction, PyInt, PyList, PyListMethods, PySequence, PySet,
7+
PySetMethods, PyString, PyTraceback, PyTuple, PyTupleMethods, PyTypeMethods,
78
};
8-
use pyo3::{Py, PyAny, PyErr, PyObject, Python, ToPyObject};
9+
use pyo3::{Bound, Py, PyAny, PyErr, PyObject, Python, ToPyObject};
910

1011
#[derive(Debug, Clone)]
1112
pub enum PythonRef {
@@ -18,7 +19,7 @@ pub enum PythonRef {
1819

1920
impl CLRepr {
2021
/// Convert python value to CLRepr
21-
pub fn from_python_ref(v: &PyAny) -> Result<Self, PyErr> {
22+
pub fn from_python_ref(v: &Bound<'_, PyAny>) -> Result<Self, PyErr> {
2223
if v.is_none() {
2324
return Ok(Self::Null);
2425
}
@@ -30,7 +31,7 @@ impl CLRepr {
3031
StringType::Normal
3132
};
3233

33-
Self::String(v.to_string(), string_type)
34+
Self::String(v.str()?.to_string(), string_type)
3435
} else if v.get_type().is_subclass_of::<PyBool>()? {
3536
Self::Bool(v.downcast::<PyBool>()?.is_true())
3637
} else if v.get_type().is_subclass_of::<PyFloat>()? {
@@ -47,7 +48,7 @@ impl CLRepr {
4748
if k.get_type().is_subclass_of::<PyString>()? {
4849
let key_str = k.downcast::<PyString>()?;
4950

50-
obj.insert(key_str.to_string(), Self::from_python_ref(v)?);
51+
obj.insert(key_str.to_string(), Self::from_python_ref(&v)?);
5152
}
5253
}
5354

@@ -57,7 +58,7 @@ impl CLRepr {
5758
let mut r = Vec::with_capacity(l.len());
5859

5960
for v in l.iter() {
60-
r.push(Self::from_python_ref(v)?);
61+
r.push(Self::from_python_ref(&v)?);
6162
}
6263

6364
Self::Array(r)
@@ -66,7 +67,7 @@ impl CLRepr {
6667
let mut r = Vec::with_capacity(l.len());
6768

6869
for v in l.iter() {
69-
r.push(Self::from_python_ref(v)?);
70+
r.push(Self::from_python_ref(&v)?);
7071
}
7172

7273
Self::Array(r)
@@ -75,12 +76,12 @@ impl CLRepr {
7576
let mut r = Vec::with_capacity(l.len());
7677

7778
for v in l.iter() {
78-
r.push(Self::from_python_ref(v)?);
79+
r.push(Self::from_python_ref(&v)?);
7980
}
8081

8182
Self::Tuple(r)
8283
} else if v.get_type().is_subclass_of::<PyFunction>()? {
83-
let fun: Py<PyFunction> = v.downcast::<PyFunction>()?.into();
84+
let fun: Py<PyFunction> = v.downcast::<PyFunction>()?.clone().unbind();
8485

8586
Self::PythonRef(PythonRef::PyFunction(fun))
8687
} else if v.get_type().is_subclass_of::<PyComplex>()? {
@@ -116,12 +117,12 @@ impl CLRepr {
116117
)));
117118
}
118119

119-
Self::PythonRef(PythonRef::PyObject(v.into()))
120+
Self::PythonRef(PythonRef::PyObject(v.clone().unbind()))
120121
})
121122
}
122123

123-
fn into_py_dict_impl(obj: CLReprObject, py: Python) -> Result<&PyDict, PyErr> {
124-
let r = PyDict::new(py);
124+
fn into_py_dict_impl(obj: CLReprObject, py: Python) -> Result<Bound<'_, PyDict>, PyErr> {
125+
let r = PyDict::new_bound(py);
125126

126127
for (k, v) in obj.into_iter() {
127128
r.set_item(k, Self::into_py_impl(v, py)?)?;
@@ -132,11 +133,11 @@ impl CLRepr {
132133

133134
fn into_py_impl(from: CLRepr, py: Python) -> Result<PyObject, PyErr> {
134135
Ok(match from {
135-
CLRepr::String(v, _) => PyString::new(py, &v).to_object(py),
136-
CLRepr::Bool(v) => PyBool::new(py, v).to_object(py),
137-
CLRepr::Float(v) => PyFloat::new(py, v).to_object(py),
136+
CLRepr::String(v, _) => PyString::new_bound(py, &v).to_object(py),
137+
CLRepr::Bool(v) => PyBool::new_bound(py, v).to_object(py),
138+
CLRepr::Float(v) => PyFloat::new_bound(py, v).to_object(py),
138139
CLRepr::Int(v) => {
139-
let py_int: &PyInt = unsafe { py.from_owned_ptr(pyo3::ffi::PyLong_FromLong(v)) };
140+
let py_int = unsafe { Bound::from_owned_ptr(py, pyo3::ffi::PyLong_FromLong(v)) };
140141

141142
py_int.to_object(py)
142143
}
@@ -147,7 +148,7 @@ impl CLRepr {
147148
elements.push(Self::into_py_impl(el, py)?);
148149
}
149150

150-
PyList::new(py, elements).to_object(py)
151+
PyList::new_bound(py, elements).to_object(py)
151152
}
152153
CLRepr::Tuple(arr) => {
153154
let mut elements = Vec::with_capacity(arr.len());
@@ -156,7 +157,7 @@ impl CLRepr {
156157
elements.push(Self::into_py_impl(el, py)?);
157158
}
158159

159-
PyTuple::new(py, elements).to_object(py)
160+
PyTuple::new_bound(py, elements).to_object(py)
160161
}
161162
CLRepr::Object(obj) => {
162163
let r = Self::into_py_dict_impl(obj, py)?;
@@ -189,7 +190,7 @@ impl CLRepr {
189190
})
190191
}
191192

192-
pub fn into_py_dict(self, py: Python) -> Result<&PyDict, PyErr> {
193+
pub fn into_py_dict(self, py: Python) -> Result<Bound<'_, PyDict>, PyErr> {
193194
Ok(match self {
194195
CLRepr::Object(obj) => Self::into_py_dict_impl(obj, py)?,
195196
other => {

packages/cubejs-backend-native/src/python/cube_config.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use convert_case::{Case, Casing};
22
use neon::prelude::*;
3-
use pyo3::{PyAny, PyResult};
3+
use pyo3::types::PyAnyMethods;
4+
use pyo3::{Bound, PyAny, PyResult};
45

56
use crate::cross::{CLRepr, CLReprObject, CLReprObjectKind};
67

@@ -69,10 +70,10 @@ impl CubeConfigPy {
6970
]
7071
}
7172

72-
pub fn attr(&mut self, config_module: &PyAny, key: &str) -> PyResult<()> {
73+
pub fn attr(&mut self, config_module: &Bound<'_, PyAny>, key: &str) -> PyResult<()> {
7374
let v = config_module.getattr(key)?;
7475
if !v.is_none() {
75-
let value = CLRepr::from_python_ref(v)?;
76+
let value = CLRepr::from_python_ref(&v)?;
7677
self.properties.insert(key.to_case(Case::Camel), value);
7778
};
7879

packages/cubejs-backend-native/src/python/entry.rs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@ use crate::python::runtime::py_runtime_init;
66
use neon::prelude::*;
77
use pyo3::exceptions::PyException;
88
use pyo3::prelude::*;
9-
use pyo3::types::{PyDict, PyFunction, PyList, PyString, PyTuple};
9+
use pyo3::types::{PyAnyMethods, PyDict, PyFunction, PyList, PyString, PyTuple};
1010
use std::path::Path;
1111

1212
fn extend_sys_path(py: Python, file_name: &String) -> PyResult<()> {
13-
let sys_path = py.import("sys")?.getattr("path")?.downcast::<PyList>()?;
13+
let binding = py.import_bound("sys")?.getattr("path")?;
14+
let sys_path = binding.downcast::<PyList>()?;
1415

1516
let config_dir = Path::new(&file_name)
1617
.parent()
1718
.unwrap_or_else(|| Path::new("."));
1819
let config_dir_str = config_dir.to_str().unwrap_or(".");
1920

20-
sys_path.insert(0, PyString::new(py, config_dir_str))?;
21+
sys_path.insert(0, PyString::new_bound(py, config_dir_str))?;
2122
Ok(())
2223
}
2324

@@ -40,9 +41,10 @@ fn python_load_config(mut cx: FunctionContext) -> JsResult<JsPromise> {
4041
env!("CARGO_MANIFEST_DIR"),
4142
"/python/cube/src/__init__.py"
4243
));
43-
PyModule::from_code(py, cube_code, "__init__.py", "cube")?;
44+
PyModule::from_code_bound(py, cube_code, "__init__.py", "cube")?;
4445

45-
let config_module = PyModule::from_code(py, &file_content_arg, &options_file_name, "")?;
46+
let config_module =
47+
PyModule::from_code_bound(py, &file_content_arg, &options_file_name, "")?;
4648
let settings_py = if config_module.hasattr("config")? {
4749
config_module.getattr("config")?
4850
} else {
@@ -60,7 +62,7 @@ fn python_load_config(mut cx: FunctionContext) -> JsResult<JsPromise> {
6062
let mut cube_conf = CubeConfigPy::new();
6163

6264
for attr_name in cube_conf.get_attrs() {
63-
cube_conf.attr(settings_py, attr_name)?;
65+
cube_conf.attr(&settings_py, attr_name)?;
6466
}
6567

6668
Ok(cube_conf)
@@ -90,9 +92,9 @@ fn python_load_model(mut cx: FunctionContext) -> JsResult<JsPromise> {
9092
env!("CARGO_MANIFEST_DIR"),
9193
"/python/cube/src/__init__.py"
9294
));
93-
PyModule::from_code(py, cube_code, "__init__.py", "cube")?;
95+
PyModule::from_code_bound(py, cube_code, "__init__.py", "cube")?;
9496

95-
let model_module = PyModule::from_code(py, &model_content, &model_file_name, "")?;
97+
let model_module = PyModule::from_code_bound(py, &model_content, &model_file_name, "")?;
9698

9799
let mut collected_functions = CLReprObject::new(CLReprObjectKind::Object);
98100
let mut collected_variables = CLReprObject::new(CLReprObjectKind::Object);
@@ -101,48 +103,55 @@ fn python_load_model(mut cx: FunctionContext) -> JsResult<JsPromise> {
101103
if model_module.hasattr("template")? {
102104
let template = model_module.getattr("template")?;
103105

104-
let functions = template.getattr("functions")?.downcast::<PyDict>()?;
106+
let functions_attr = template.getattr("functions")?;
107+
let functions = functions_attr.downcast::<PyDict>()?;
105108
for (local_key, local_value) in functions.iter() {
106109
if local_value.is_instance_of::<PyFunction>() {
107-
let fun: Py<PyFunction> = local_value.downcast::<PyFunction>()?.into();
110+
let fun: Py<PyFunction> =
111+
local_value.downcast::<PyFunction>()?.clone().unbind();
108112
collected_functions.insert(
109-
local_key.to_string(),
113+
local_key.str()?.to_string(),
110114
CLRepr::PythonRef(PythonRef::PyExternalFunction(fun)),
111115
);
112116
}
113117
}
114118

115-
let variables = template.getattr("variables")?.downcast::<PyDict>()?;
119+
let variables_attr = template.getattr("variables")?;
120+
let variables = variables_attr.downcast::<PyDict>()?;
116121
for (local_key, local_value) in variables.iter() {
117-
collected_variables
118-
.insert(local_key.to_string(), CLRepr::from_python_ref(local_value)?);
122+
collected_variables.insert(
123+
local_key.str()?.to_string(),
124+
CLRepr::from_python_ref(&local_value)?,
125+
);
119126
}
120127

121-
let filters = template.getattr("filters")?.downcast::<PyDict>()?;
128+
let filters_attr = template.getattr("filters")?;
129+
let filters = filters_attr.downcast::<PyDict>()?;
122130
for (local_key, local_value) in filters.iter() {
123-
let fun: Py<PyFunction> = local_value.downcast::<PyFunction>()?.into();
131+
let fun: Py<PyFunction> = local_value.downcast::<PyFunction>()?.clone().unbind();
124132
collected_filters.insert(
125-
local_key.to_string(),
133+
local_key.str()?.to_string(),
126134
CLRepr::PythonRef(PythonRef::PyExternalFunction(fun)),
127135
);
128136
}
129137
} else {
130138
// backward compatibility, was used in private preview, not as Public API
131139
// TODO: Remove after 1.4
132-
let inspect_module = py.import("inspect")?;
140+
let inspect_module = py.import_bound("inspect")?;
133141
let args = (model_module, inspect_module.getattr("isfunction")?);
134-
let functions_with_names = inspect_module
135-
.call_method1("getmembers", args)?
136-
.downcast::<PyList>()?;
142+
let getmembers_result = inspect_module.call_method1("getmembers", args)?;
143+
let functions_with_names = getmembers_result.downcast::<PyList>()?;
137144

138145
for function_details in functions_with_names.iter() {
139146
let function_details = function_details.downcast::<PyTuple>()?;
140-
let fun_name = function_details.get_item(0)?.downcast::<PyString>()?;
141-
let fun = function_details.get_item(1)?.downcast::<PyFunction>()?;
147+
let fun_name_item = function_details.get_item(0)?;
148+
let fun_name = fun_name_item.downcast::<PyString>()?;
149+
let fun_item = function_details.get_item(1)?;
150+
let fun = fun_item.downcast::<PyFunction>()?;
142151

143152
let has_attr = fun.hasattr("cube_context_func")?;
144153
if has_attr {
145-
let fun: Py<PyFunction> = fun.into();
154+
let fun: Py<PyFunction> = fun.clone().unbind();
146155
collected_functions.insert(
147156
fun_name.to_string(),
148157
CLRepr::PythonRef(PythonRef::PyExternalFunction(fun)),

packages/cubejs-backend-native/src/python/neon_py.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub(crate) fn format_python_error(py_err: PyErr) -> String {
55
let err = format!("Python error: {}", py_err);
66

77
let bt = Python::with_gil(move |py| -> PyResult<Option<String>> {
8-
if let Some(trace_back) = py_err.traceback(py) {
8+
if let Some(trace_back) = py_err.traceback_bound(py) {
99
Ok(Some(trace_back.format()?))
1010
} else {
1111
Ok(None)

packages/cubejs-backend-native/src/python/runtime.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,26 +96,27 @@ impl PyRuntime {
9696

9797
let task_result = Python::with_gil(move |py| -> PyResult<PyScheduledFunResult> {
9898
let mut prep_tuple = Vec::with_capacity(args.len());
99-
let mut py_kwargs = None;
99+
let mut kwargs_dict_opt = None;
100100

101101
for arg in args {
102102
if arg.is_kwarg() {
103-
py_kwargs = Some(arg.into_py_dict(py)?);
103+
kwargs_dict_opt = Some(arg.into_py_dict(py)?);
104104
} else {
105105
prep_tuple.push(arg.into_py(py)?);
106106
}
107107
}
108108

109-
let py_args = PyTuple::new(py, prep_tuple);
110-
let call_res = fun.call(py, py_args, py_kwargs)?;
109+
let py_args = PyTuple::new_bound(py, prep_tuple);
110+
let py_kwargs = kwargs_dict_opt.as_ref();
111+
let call_res = fun.call_bound(py, py_args, py_kwargs)?;
111112

112113
let is_coroutine = unsafe { pyo3::ffi::PyCoro_CheckExact(call_res.as_ptr()) == 1 };
113114
if is_coroutine {
114115
let fut = pyo3_async_runtimes::tokio::into_future(call_res.bind(py).clone())?;
115116
Ok(PyScheduledFunResult::Poll(Box::pin(fut)))
116117
} else {
117118
Ok(PyScheduledFunResult::Ready(CLRepr::from_python_ref(
118-
call_res.as_ref(py),
119+
&call_res.bind(py),
119120
)?))
120121
}
121122
});
@@ -155,7 +156,7 @@ impl PyRuntime {
155156

156157
let res = Python::with_gil(move |py| -> Result<CLRepr, PyErr> {
157158
let res = match fut_res {
158-
Ok(r) => CLRepr::from_python_ref(r.as_ref(py)),
159+
Ok(r) => CLRepr::from_python_ref(&r.bind(py)),
159160
Err(err) => Err(err),
160161
};
161162

packages/cubejs-backend-native/src/python/utils.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub fn python_fn_call_sync(py_fun: &Py<PyFunction>, arguments: Vec<CLRepr>) -> P
1111
args_tuple.push(arg.into_py(py)?);
1212
}
1313

14-
let tuple = PyTuple::new(py, args_tuple);
14+
let tuple = PyTuple::new_bound(py, args_tuple);
1515

1616
let call_res = py_fun.call1(py, tuple)?;
1717

@@ -21,7 +21,7 @@ pub fn python_fn_call_sync(py_fun: &Py<PyFunction>, arguments: Vec<CLRepr>) -> P
2121
"Calling function with async response is not supported",
2222
))
2323
} else {
24-
CLRepr::from_python_ref(call_res.as_ref(py))
24+
CLRepr::from_python_ref(&call_res.bind(py))
2525
}
2626
})
2727
}
@@ -34,7 +34,7 @@ pub fn python_obj_call_sync(py_fun: &PyObject, arguments: Vec<CLRepr>) -> PyResu
3434
args_tuple.push(arg.into_py(py)?);
3535
}
3636

37-
let tuple = PyTuple::new(py, args_tuple);
37+
let tuple = PyTuple::new_bound(py, args_tuple);
3838

3939
let call_res = py_fun.call1(py, tuple)?;
4040

@@ -44,7 +44,7 @@ pub fn python_obj_call_sync(py_fun: &PyObject, arguments: Vec<CLRepr>) -> PyResu
4444
"Calling object with async response is not supported",
4545
))
4646
} else {
47-
CLRepr::from_python_ref(call_res.as_ref(py))
47+
CLRepr::from_python_ref(&call_res.bind(py))
4848
}
4949
})
5050
}
@@ -64,7 +64,7 @@ where
6464
args_tuple.push(arg.into_py(py)?);
6565
}
6666

67-
let tuple = PyTuple::new(py, args_tuple);
67+
let tuple = PyTuple::new_bound(py, args_tuple);
6868

6969
let call_res = py_fun.call_method1(py, name, tuple)?;
7070

@@ -74,7 +74,7 @@ where
7474
"Calling object method with async response is not supported",
7575
))
7676
} else {
77-
CLRepr::from_python_ref(call_res.as_ref(py))
77+
CLRepr::from_python_ref(&call_res.bind(py))
7878
}
7979
})
8080
}

0 commit comments

Comments
 (0)