Skip to content

Commit ceee578

Browse files
authored
Merge pull request #96 from influxdata/crepererum/http
feat: HTTP interface for Python guests
2 parents 52b2f1b + 10bf869 commit ceee578

File tree

10 files changed

+1867
-11
lines changed

10 files changed

+1867
-11
lines changed

Cargo.lock

Lines changed: 159 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ datafusion-udf-wasm-bundle = { path = "guests/bundle", version = "0.1.0" }
2424
datafusion-udf-wasm-guest = { path = "guests/rust", version = "0.1.0" }
2525
datafusion-udf-wasm-python = { path = "guests/python", version = "0.1.0" }
2626
tokio = { version = "1.48.0", default-features = false }
27-
pyo3 = { version = "0.27.0", default-features = false }
27+
pyo3 = { version = "0.27.0", default-features = false, features = ["macros"] }
2828
tar = { version = "0.4.44", default-features = false }
2929
tempfile = { version = "3.23.0", default-features = false }
30+
wasip2 = { version = "1" }
3031
wasmtime = { version = "37.0.2", default-features = false, features = ["async", "cranelift"] }
3132
wasmtime-wasi = { version = "37.0.0", default-features = false }
3233
wasmtime-wasi-http = { version = "37.0.0", default-features = false, features = ["default-send-request"] }

guests/python/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ datafusion-common.workspace = true
1818
datafusion-expr.workspace = true
1919
datafusion-udf-wasm-guest.workspace = true
2020
pyo3.workspace = true
21+
wasip2.workspace = true
2122

2223
[build-dependencies]
2324
tar.workspace = true

guests/python/src/lib.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//! [`pyo3`]: https://pyo3.rs/
66
use std::any::Any;
77
use std::ops::{ControlFlow, Range};
8-
use std::sync::Arc;
8+
use std::sync::{Arc, Once};
99

1010
use arrow::datatypes::DataType;
1111
use datafusion_common::{
@@ -23,6 +23,7 @@ use crate::signature::PythonFn;
2323
mod conversion;
2424
mod error;
2525
mod inspect;
26+
mod python_modules;
2627
mod signature;
2728

2829
/// Supported Python version range.
@@ -271,15 +272,20 @@ fn root() -> Option<Vec<u8>> {
271272
///
272273
/// [Python Standard Library]: https://docs.python.org/3/library/index.html
273274
fn init_python() {
274-
Python::initialize();
275-
276-
Python::attach(|py| {
277-
let version_info = py.version_info();
278-
let version_tuple = (version_info.major, version_info.minor, version_info.patch);
279-
assert!(
280-
PYTHON_VERSION_RANGE.contains(&version_tuple),
281-
"Unsupported python version: {version_tuple:?}, supported range is {PYTHON_VERSION_RANGE:?}",
282-
);
275+
static INIT: Once = Once::new();
276+
277+
INIT.call_once(|| {
278+
python_modules::register();
279+
Python::initialize();
280+
281+
Python::attach(|py| {
282+
let version_info = py.version_info();
283+
let version_tuple = (version_info.major, version_info.minor, version_info.patch);
284+
assert!(
285+
PYTHON_VERSION_RANGE.contains(&version_tuple),
286+
"Unsupported python version: {version_tuple:?}, supported range is {PYTHON_VERSION_RANGE:?}",
287+
);
288+
});
283289
});
284290
}
285291

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//! Error handling helpers.
2+
use pyo3::{exceptions::PyValueError, prelude::*};
3+
4+
/// A resource (handle) was already used/moved/closed.
5+
#[derive(Debug, Default, Clone, Copy)]
6+
pub(crate) struct ResourceMoved;
7+
8+
impl std::fmt::Display for ResourceMoved {
9+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10+
write!(f, "ResourceMoved")
11+
}
12+
}
13+
14+
impl std::error::Error for ResourceMoved {}
15+
16+
impl From<ResourceMoved> for PyErr {
17+
fn from(e: ResourceMoved) -> Self {
18+
PyValueError::new_err(e.to_string())
19+
}
20+
}
21+
22+
/// Extensions trait for [`Option`] to simplify the work with [`ResourceMoved`].
23+
pub(crate) trait ResourceMovedOptionExt {
24+
/// Option type.
25+
type T;
26+
27+
/// Require the [`Option`] to be [`Some`], otherwise fail with [`ResourceMoved`].
28+
fn require_resource(self) -> Result<Self::T, ResourceMoved>;
29+
}
30+
31+
impl<T> ResourceMovedOptionExt for Option<T> {
32+
type T = T;
33+
34+
fn require_resource(self) -> Result<Self::T, ResourceMoved> {
35+
self.ok_or(ResourceMoved)
36+
}
37+
}

0 commit comments

Comments
 (0)