diff --git a/sentry_streams/Cargo.lock b/sentry_streams/Cargo.lock index 63c00976..57072b92 100644 --- a/sentry_streams/Cargo.lock +++ b/sentry_streams/Cargo.lock @@ -863,12 +863,6 @@ dependencies = [ "hashbrown 0.15.2", ] -[[package]] -name = "indoc" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" - [[package]] name = "ipnet" version = "2.11.0" @@ -955,15 +949,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "metrics" version = "0.24.3" @@ -1307,37 +1292,32 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.24.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1c6c3591120564d64db2261bec5f910ae454f01def849b9c22835a84695e86" +checksum = "cf85e27e86080aafd5a22eae58a162e133a589551542b3e5cee4beb27e54f8e1" dependencies = [ - "cfg-if", - "indoc", "libc", - "memoffset", "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", - "unindent", ] [[package]] name = "pyo3-build-config" -version = "0.24.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b6c2b34cf71427ea37c7001aefbaeb85886a074795e35f161f5aecc7620a7a" +checksum = "8bf94ee265674bf76c09fa430b0e99c26e319c945d96ca0d5a8215f31bf81cf7" dependencies = [ - "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" -version = "0.24.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5507651906a46432cdda02cd02dd0319f6064f1374c9147c45b978621d2c3a9c" +checksum = "491aa5fc66d8059dd44a75f4580a2962c1862a1c2945359db36f6c2818b748dc" dependencies = [ "libc", "pyo3-build-config", @@ -1345,9 +1325,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.24.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d394b5b4fd8d97d48336bb0dd2aebabad39f1d294edd6bcd2cccf2eefe6f42" +checksum = "f5d671734e9d7a43449f8480f8b38115df67bef8d21f76837fa75ee7aaa5e52e" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -1357,9 +1337,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.24.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd72da09cfa943b1080f621f024d2ef7e2773df7badd51aa30a2be1f8caa7c8e" +checksum = "22faaa1ce6c430a1f71658760497291065e6450d7b5dc2bcf254d49f66ee700a" dependencies = [ "heck", "proc-macro2", @@ -1599,7 +1579,6 @@ dependencies = [ "metrics-exporter-dogstatsd", "parking_lot", "pyo3", - "pyo3-build-config", "rand 0.8.5", "rdkafka", "reqwest", @@ -1977,9 +1956,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.13.2" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tempfile" @@ -2270,12 +2249,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" -[[package]] -name = "unindent" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" - [[package]] name = "untrusted" version = "0.9.0" diff --git a/sentry_streams/Cargo.toml b/sentry_streams/Cargo.toml index 0b098e69..98b94e22 100644 --- a/sentry_streams/Cargo.toml +++ b/sentry_streams/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -pyo3 = { version = "0.24.0" } +pyo3 = { version = "0.28.2" } serde = { version = "1.0", features = ["derive"] } sentry_arroyo = { version = "2.38.2", features = ["ssl"] } chrono = "0.4.40" @@ -39,9 +39,6 @@ cli = ["dep:clap", "pyo3/auto-initialize"] parking_lot = "0.12.1" pyo3 = { version = "*", features = ["auto-initialize"] } -[build-dependencies] -pyo3-build-config = "*" - # For now (while we are still rolling out streams to SBC), let's enable maximal # debug information. There should only be overhead in space and when many # stacktraces are generated (thousands/sec) diff --git a/sentry_streams/pyproject.toml b/sentry_streams/pyproject.toml index 95081b41..3452c256 100644 --- a/sentry_streams/pyproject.toml +++ b/sentry_streams/pyproject.toml @@ -9,6 +9,12 @@ description = "The python Sentry Streaming API" readme = "README.md" requires-python = ">=3.11" +classifiers = [ + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", +] dependencies = [ "requests>=2.32.3", diff --git a/sentry_streams/sentry_streams/examples/rust_simple_map_filter/rust_transforms/Cargo.toml b/sentry_streams/sentry_streams/examples/rust_simple_map_filter/rust_transforms/Cargo.toml index d7adf896..47fd06b5 100644 --- a/sentry_streams/sentry_streams/examples/rust_simple_map_filter/rust_transforms/Cargo.toml +++ b/sentry_streams/sentry_streams/examples/rust_simple_map_filter/rust_transforms/Cargo.toml @@ -12,7 +12,7 @@ name = "runner" path = "src/main.rs" [dependencies] -pyo3 = { version = "0.24" } +pyo3 = { version = "0.28" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/sentry_streams/src/callers.rs b/sentry_streams/src/callers.rs index 867b4305..63ee9289 100644 --- a/sentry_streams/src/callers.rs +++ b/sentry_streams/src/callers.rs @@ -1,4 +1,4 @@ -use pyo3::{import_exception, prelude::*, types::PyTuple}; +use pyo3::{call::PyCallArgs, import_exception, prelude::*}; import_exception!(sentry_streams.pipeline.exception, InvalidMessageError); @@ -16,7 +16,7 @@ pub fn try_apply_py<'py, N>( args: N, ) -> ApplyResult> where - N: IntoPyObject<'py, Target = PyTuple>, + N: PyCallArgs<'py>, { callable.call1(py, args).map_err(|py_err| { py_err.print(py); diff --git a/sentry_streams/src/committable.rs b/sentry_streams/src/committable.rs index 86b1c9d0..4ee8200a 100644 --- a/sentry_streams/src/committable.rs +++ b/sentry_streams/src/committable.rs @@ -40,7 +40,7 @@ pub fn convert_py_committable( let mut committable = BTreeMap::new(); let dict = py_committable.bind(py); for (key, value) in dict.iter() { - let partition = key.downcast::()?; + let partition = key.cast::()?; let topic: String = partition.get_item(0)?.extract()?; let index: u16 = partition.get_item(1)?.extract()?; let offset: u64 = value.extract()?; diff --git a/sentry_streams/src/consumer.rs b/sentry_streams/src/consumer.rs index afc8e520..3b77dee7 100644 --- a/sentry_streams/src/consumer.rs +++ b/sentry_streams/src/consumer.rs @@ -329,7 +329,7 @@ mod tests { if let PyStreamingMessage::RawMessage { ref content } = py_payload { let payload = content.getattr(py, "payload").unwrap(); - let down: &Bound = payload.bind(py).downcast().unwrap(); + let down: &Bound = payload.bind(py).cast().unwrap(); let payload_bytes: &[u8] = down.as_bytes(); assert_eq!(payload_bytes, payload_data); } else { @@ -355,7 +355,7 @@ mod tests { .getattr(py, "payload") .unwrap() .bind(py) - .downcast::() + .cast::() .unwrap() .as_bytes() .to_vec(); diff --git a/sentry_streams/src/ffi.rs b/sentry_streams/src/ffi.rs index b6420dbe..57e0cfa5 100644 --- a/sentry_streams/src/ffi.rs +++ b/sentry_streams/src/ffi.rs @@ -158,7 +158,7 @@ macro_rules! rust_function { let rust_msg = $crate::ffi::convert_py_message_to_rust::<$input_type>(py, &py_msg)?; // Release GIL and call Rust function - let result_msg = py.allow_threads(|| { + let result_msg = py.detach(|| { // clone metadata, but try very hard to avoid cloning the payload let (payload, metadata) = rust_msg.take(); let metadata_clone = metadata.clone(); diff --git a/sentry_streams/src/gcs_writer.rs b/sentry_streams/src/gcs_writer.rs index f4df1eb8..9e825232 100644 --- a/sentry_streams/src/gcs_writer.rs +++ b/sentry_streams/src/gcs_writer.rs @@ -36,7 +36,7 @@ fn pybytes_to_bytes(message: &PyStreamingMessage, py: Python<'_>) -> PyResult { let payload_content = content.bind(py).getattr("payload").unwrap(); - let py_bytes: &Bound = payload_content.downcast().unwrap(); + let py_bytes: &Bound = payload_content.cast().unwrap(); Ok(py_bytes.as_bytes().to_vec()) } } diff --git a/sentry_streams/src/kafka_config.rs b/sentry_streams/src/kafka_config.rs index 89beeddd..d9bf9559 100644 --- a/sentry_streams/src/kafka_config.rs +++ b/sentry_streams/src/kafka_config.rs @@ -10,7 +10,7 @@ use sentry_arroyo::backends::kafka::config::KafkaConfig; use sentry_arroyo::backends::kafka::InitialOffset as KafkaInitialOffset; use std::collections::HashMap; -#[pyclass] +#[pyclass(from_py_object)] #[derive(Debug, Clone, Copy, Default)] pub enum InitialOffset { #[default] @@ -34,7 +34,7 @@ impl From for KafkaInitialOffset { } } -#[pyclass] +#[pyclass(from_py_object)] #[derive(Debug, Clone)] pub struct OffsetResetConfig { #[pyo3(get, set)] @@ -55,7 +55,7 @@ impl OffsetResetConfig { } // Python version of the Kafka consumer configuration -#[pyclass] +#[pyclass(from_py_object)] #[derive(Debug, Clone)] pub struct PyKafkaConsumerConfig { bootstrap_servers: Vec, @@ -101,7 +101,7 @@ impl From for KafkaConfig { } } -#[pyclass] +#[pyclass(from_py_object)] #[derive(Debug, Clone)] pub struct PyKafkaProducerConfig { bootstrap_servers: Vec, diff --git a/sentry_streams/src/messages.rs b/sentry_streams/src/messages.rs index e3a6492a..86ec8799 100644 --- a/sentry_streams/src/messages.rs +++ b/sentry_streams/src/messages.rs @@ -54,7 +54,7 @@ pub fn headers_to_vec(py: Python<'_>, headers: Py) -> PyResult PyResult<(String, Vec)> { let tuple_i = item?; - let tuple = tuple_i.downcast::()?; + let tuple = tuple_i.cast::()?; let key = tuple.get_item(0)?.unbind().extract(py)?; let value: Vec = tuple.get_item(1)?.unbind().extract(py)?; Ok((key, value)) @@ -333,7 +333,7 @@ pub fn into_pyraw(py: Python<'_>, message: RawMessage) -> PyResult }, RawMessage { content: Py }, @@ -454,12 +454,12 @@ impl From> for PyStreamingMessage { traced_with_gil!(|py| { let bound = value.clone_ref(py).into_bound(py); if bound.is_instance_of::() { - let content = bound.downcast::()?; + let content = bound.cast::()?; Ok(PyStreamingMessage::PyAnyMessage { content: content.clone().unbind(), }) } else if bound.is_instance_of::() { - let content = bound.downcast::()?; + let content = bound.cast::()?; Ok(PyStreamingMessage::RawMessage { content: content.clone().unbind(), }) @@ -481,16 +481,16 @@ impl TryFrom> for WatermarkMessage { traced_with_gil!(|py| { let bound = value.clone_ref(py).into_bound(py); if bound.is_instance_of::() { - let py_watermark = bound.downcast::()?; + let py_watermark = bound.cast::()?; let py_committable = py_watermark .getattr("committable")? - .downcast::()? + .cast::()? .clone() .unbind(); let committable = convert_py_committable(py, py_committable).unwrap(); let timestamp = match py_watermark .getattr("timestamp")? - .downcast::()? + .cast::()? .extract::() { Ok(time) => time, diff --git a/sentry_streams/src/metrics_config.rs b/sentry_streams/src/metrics_config.rs index ad7e64d2..a45e3653 100644 --- a/sentry_streams/src/metrics_config.rs +++ b/sentry_streams/src/metrics_config.rs @@ -7,7 +7,7 @@ use pyo3::prelude::*; use std::collections::HashMap; -#[pyclass] +#[pyclass(from_py_object)] #[derive(Debug, Clone)] pub struct PyMetricConfig { host: String, diff --git a/sentry_streams/src/python_operator.rs b/sentry_streams/src/python_operator.rs index 0dc6ff54..1a62a620 100644 --- a/sentry_streams/src/python_operator.rs +++ b/sentry_streams/src/python_operator.rs @@ -65,11 +65,11 @@ impl PythonAdapter { /// the Python delegate. fn handle_py_return_value(&mut self, py: Python<'_>, payloads: Vec>) { for py_payload in payloads { - let entry = py_payload.downcast_bound::(py).unwrap(); + let entry = py_payload.cast_bound::(py).unwrap(); let payload: Py = entry.get_item(0).unwrap().unbind(); let committable: Py = entry.get_item(1).unwrap().unbind(); let committable_dict = committable - .downcast_bound::(py) + .cast_bound::(py) .unwrap() .as_unbound() .clone_ref(py); diff --git a/sentry_streams/src/routes.rs b/sentry_streams/src/routes.rs index a3193a2d..09b749a6 100644 --- a/sentry_streams/src/routes.rs +++ b/sentry_streams/src/routes.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; /// /// The waypoints sequence contains the branches taken by the message /// in order following the pipeline. -#[pyclass] +#[pyclass(from_py_object)] #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] pub struct Route { /// The name of the streaming source this route starts from. diff --git a/sentry_streams/src/sinks.rs b/sentry_streams/src/sinks.rs index c9df8587..dd539087 100644 --- a/sentry_streams/src/sinks.rs +++ b/sentry_streams/src/sinks.rs @@ -104,7 +104,7 @@ fn to_kafka_payload(message: Message) -> Message { RoutedValuePayload::PyStreamingMessage(PyStreamingMessage::RawMessage { ref content }) => { traced_with_gil!(|py| { let payload_content = content.bind(py).getattr("payload").unwrap(); - let py_bytes: &Bound = payload_content.downcast().unwrap(); + let py_bytes: &Bound = payload_content.cast().unwrap(); let raw_bytes = py_bytes.as_bytes(); let mut headers = Headers::new(); headers = headers.insert("is_watermark", Some(vec![0])); diff --git a/sentry_streams/src/testutils.rs b/sentry_streams/src/testutils.rs index e3aadc4e..abf13379 100644 --- a/sentry_streams/src/testutils.rs +++ b/sentry_streams/src/testutils.rs @@ -142,7 +142,7 @@ pub fn initialize_python() { let python_path = std::env::var("STREAMS_TEST_PYTHONPATH").unwrap(); let python_path: Vec<_> = python_path.split(':').map(String::from).collect(); - Python::with_gil(|py| -> PyResult<()> { + Python::attach(|py| -> PyResult<()> { PyModule::import(py, "sys")?.setattr("executable", python_executable)?; PyModule::import(py, "sys")?.setattr("path", python_path)?; Ok(()) diff --git a/sentry_streams/src/utils.rs b/sentry_streams/src/utils.rs index 25e49683..1a034a39 100644 --- a/sentry_streams/src/utils.rs +++ b/sentry_streams/src/utils.rs @@ -49,7 +49,7 @@ where let thread_id = thread::current().id(); let start_time = Instant::now(); - Python::with_gil(|py| { + Python::attach(|py| { let acquire_time = Instant::now().duration_since(start_time); if acquire_time > warn_threshold { diff --git a/sentry_streams/tests/rust_test_functions/Cargo.toml b/sentry_streams/tests/rust_test_functions/Cargo.toml index 1beca45c..fe5a0335 100644 --- a/sentry_streams/tests/rust_test_functions/Cargo.toml +++ b/sentry_streams/tests/rust_test_functions/Cargo.toml @@ -8,7 +8,7 @@ name = "rust_test_functions" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.24" } +pyo3 = { version = "0.28" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" paste = "1.0" diff --git a/sentry_streams/uv.lock b/sentry_streams/uv.lock index fab98f60..3a25fc96 100644 --- a/sentry_streams/uv.lock +++ b/sentry_streams/uv.lock @@ -893,7 +893,7 @@ wheels = [ [[package]] name = "sentry-streams" -version = "0.0.38" +version = "0.0.39" source = { editable = "." } dependencies = [ { name = "click" }, diff --git a/sentry_streams_k8s/pyproject.toml b/sentry_streams_k8s/pyproject.toml index 653237fe..0ac51218 100644 --- a/sentry_streams_k8s/pyproject.toml +++ b/sentry_streams_k8s/pyproject.toml @@ -8,6 +8,12 @@ version = "0.0.4" description = "Kubernetes integration for Sentry Streams" readme = "README.md" requires-python = ">=3.11" +classifiers = [ + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", +] dependencies = [ "jsonschema>=4.23.0", "requests>=2.32.3",