chalk-remote-call-python 1.10.7__tar.gz → 1.10.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. {chalk_remote_call_python-1.10.7/chalk_remote_call_python.egg-info → chalk_remote_call_python-1.10.8}/PKG-INFO +1 -1
  2. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/Cargo.lock +1 -0
  3. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/Cargo.toml +3 -0
  4. chalk_remote_call_python-1.10.8/chalk-remote-call-rs/chalk-remote-call-server/build.rs +15 -0
  5. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/python_bridge.rs +117 -14
  6. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/self_consumer.rs +1 -1
  7. chalk_remote_call_python-1.10.8/chalk_remote_call/_version.py +1 -0
  8. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8/chalk_remote_call_python.egg-info}/PKG-INFO +1 -1
  9. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call_python.egg-info/SOURCES.txt +1 -0
  10. chalk_remote_call_python-1.10.7/chalk_remote_call/_version.py +0 -1
  11. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/MANIFEST.in +0 -0
  12. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/README.md +0 -0
  13. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/Cargo.toml +0 -0
  14. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-proto/Cargo.toml +0 -0
  15. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.auth.v1.rs +0 -0
  16. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.common.v1.rs +0 -0
  17. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.rs +0 -0
  18. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.tonic.rs +0 -0
  19. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.utils.v1.rs +0 -0
  20. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/descriptor.bin +0 -0
  21. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-proto/src/lib.rs +0 -0
  22. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/async_service.rs +0 -0
  23. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/coalesce.rs +0 -0
  24. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/fnq_client.rs +0 -0
  25. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/lib.rs +0 -0
  26. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/metrics.rs +0 -0
  27. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/server.rs +0 -0
  28. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/chalk-remote-call-server/src/service.rs +0 -0
  29. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk-remote-call-rs/rust-toolchain.toml +0 -0
  30. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/__init__.py +0 -0
  31. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/__main__.py +0 -0
  32. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/__init__.py +0 -0
  33. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/__init__.py +0 -0
  34. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/auth/__init__.py +0 -0
  35. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/auth/v1/__init__.py +0 -0
  36. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2.py +0 -0
  37. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2_grpc.py +0 -0
  38. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/common/__init__.py +0 -0
  39. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/common/v1/__init__.py +0 -0
  40. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2.py +0 -0
  41. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2_grpc.py +0 -0
  42. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/runtime/__init__.py +0 -0
  43. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/runtime/v1/__init__.py +0 -0
  44. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/runtime/v1/fnq_consumer_pb2.py +0 -0
  45. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/runtime/v1/fnq_consumer_pb2_grpc.py +0 -0
  46. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2.py +0 -0
  47. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2_grpc.py +0 -0
  48. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/__init__.py +0 -0
  49. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/__init__.py +0 -0
  50. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2.py +0 -0
  51. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2_grpc.py +0 -0
  52. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2.py +0 -0
  53. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2_grpc.py +0 -0
  54. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/large_pb2.py +0 -0
  55. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/large_pb2_grpc.py +0 -0
  56. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2.py +0 -0
  57. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2_grpc.py +0 -0
  58. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/_native.pyi +0 -0
  59. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/arrow_utils.py +0 -0
  60. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/cli.py +0 -0
  61. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/errors.py +0 -0
  62. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/handler_loader.py +0 -0
  63. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/input_transform.py +0 -0
  64. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/logging.py +0 -0
  65. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/server.py +0 -0
  66. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/servicer.py +0 -0
  67. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call/tracing.py +0 -0
  68. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call_python.egg-info/dependency_links.txt +0 -0
  69. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call_python.egg-info/entry_points.txt +0 -0
  70. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call_python.egg-info/requires.txt +0 -0
  71. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/chalk_remote_call_python.egg-info/top_level.txt +0 -0
  72. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/pyproject.toml +0 -0
  73. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/setup.cfg +0 -0
  74. {chalk_remote_call_python-1.10.7 → chalk_remote_call_python-1.10.8}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalk-remote-call-python
3
- Version: 1.10.7
3
+ Version: 1.10.8
4
4
  Summary: Chalk remote call Python runtime interface client
5
5
  Author: Chalk AI, Inc.
6
6
  Project-URL: Homepage, https://chalk.ai
@@ -548,6 +548,7 @@ dependencies = [
548
548
  "futures-util",
549
549
  "prost 0.13.5",
550
550
  "pyo3",
551
+ "pyo3-build-config",
551
552
  "redis",
552
553
  "serde_json",
553
554
  "tokio",
@@ -11,6 +11,9 @@ crate-type = ["cdylib"]
11
11
  default = ["extension-module"]
12
12
  extension-module = ["pyo3/extension-module"]
13
13
 
14
+ [build-dependencies]
15
+ pyo3-build-config = { version = "0.29", features = ["resolve-config"] }
16
+
14
17
  [dependencies]
15
18
  chalk-remote-call-proto = { path = "../chalk-remote-call-proto" }
16
19
  redis = { version = "1.0.2", features = ["aio", "tokio-comp", "streams", "connection-manager"] }
@@ -0,0 +1,15 @@
1
+ fn main() {
2
+ println!("cargo:rerun-if-env-changed=CARGO_FEATURE_EXTENSION_MODULE");
3
+ if std::env::var_os("CARGO_FEATURE_EXTENSION_MODULE").is_some() {
4
+ return;
5
+ }
6
+
7
+ let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
8
+ if matches!(target_os.as_str(), "linux" | "macos") {
9
+ // Embedding test binaries need the same Python library that PyO3 links,
10
+ // even when a managed interpreter installs it outside system paths.
11
+ if let Some(lib_dir) = pyo3_build_config::get().lib_dir() {
12
+ println!("cargo:rustc-link-arg=-Wl,-rpath,{lib_dir}");
13
+ }
14
+ }
15
+ }
@@ -45,7 +45,7 @@ impl PythonHandler {
45
45
  /// into a shared buffer). The only difference between the two paths is which
46
46
  /// emitter object `process_batches` is handed.
47
47
  async fn call_with_emitter<F>(
48
- &self,
48
+ self: &Arc<Self>,
49
49
  ipc_bytes: Vec<u8>,
50
50
  function_name: String,
51
51
  metadata: HashMap<String, String>,
@@ -55,12 +55,13 @@ impl PythonHandler {
55
55
  where
56
56
  F: FnOnce(Python<'_>) -> PyResult<Py<PyAny>> + Send + 'static,
57
57
  {
58
- let (handler, process_fn) =
59
- Python::attach(|py| (self.handler.clone_ref(py), self.process_fn.clone_ref(py)));
60
- let arg_names = self.arg_names.clone();
61
-
58
+ // GIL acquisition can block, so only clone the Rust owner on the runtime worker.
59
+ let owner = Arc::clone(self);
62
60
  tokio::task::spawn_blocking(move || {
63
61
  Python::attach(|py| -> Result<(), PythonError> {
62
+ let handler = owner.handler.clone_ref(py);
63
+ let process_fn = &owner.process_fn;
64
+ let arg_names = &owner.arg_names;
64
65
  let py_bytes = PyBytes::new(py, &ipc_bytes).into_any().unbind();
65
66
  let py_ctx = build_context(py, &function_name, &metadata, &peer)?
66
67
  .into_any()
@@ -81,7 +82,7 @@ impl PythonHandler {
81
82
  /// Non-batched streaming dispatch. Calls `process_batches(..., emit)` so
82
83
  /// generator results are sent to the gRPC stream as each yield is encoded.
83
84
  pub async fn call_streaming(
84
- &self,
85
+ self: &Arc<Self>,
85
86
  ipc_bytes: Vec<u8>,
86
87
  function_name: String,
87
88
  metadata: HashMap<String, String>,
@@ -100,7 +101,7 @@ impl PythonHandler {
100
101
  /// value, so completion never depends on emitter teardown timing (which is
101
102
  /// what caused a Python 3.10 hang in the channel-drain version).
102
103
  pub async fn call_into_buffer(
103
- &self,
104
+ self: &Arc<Self>,
104
105
  ipc_bytes: Vec<u8>,
105
106
  function_name: String,
106
107
  metadata: HashMap<String, String>,
@@ -117,15 +118,16 @@ impl PythonHandler {
117
118
  /// `process_batches_coalesced`. Returns one IPC-encoded response per
118
119
  /// caller, in input order.
119
120
  pub async fn call_coalesced(
120
- &self,
121
+ self: &Arc<Self>,
121
122
  callers: Vec<CallerInput>,
122
123
  ) -> Result<Vec<Vec<u8>>, PythonError> {
123
- let (handler, process_fn) =
124
- Python::attach(|py| (self.handler.clone_ref(py), self.process_fn.clone_ref(py)));
125
- let arg_names = self.arg_names.clone();
126
-
124
+ // GIL acquisition can block, so only clone the Rust owner on the runtime worker.
125
+ let owner = Arc::clone(self);
127
126
  tokio::task::spawn_blocking(move || {
128
127
  Python::attach(|py| -> Result<Vec<Vec<u8>>, PythonError> {
128
+ let handler = &owner.handler;
129
+ let process_fn = &owner.process_fn;
130
+ let arg_names = &owner.arg_names;
129
131
  let py_inputs = PyList::empty(py);
130
132
  let py_contexts = PyList::empty(py);
131
133
  for c in &callers {
@@ -139,8 +141,8 @@ impl PythonHandler {
139
141
  let py_arg_names = build_arg_names(py, arg_names.as_deref())?;
140
142
  invoke_process_fn(
141
143
  py,
142
- &process_fn,
143
- &handler,
144
+ process_fn,
145
+ handler,
144
146
  py_inputs.into_any().unbind(),
145
147
  py_arg_names,
146
148
  py_contexts.into_any().unbind(),
@@ -389,3 +391,104 @@ fn format_python_traceback(py: Python<'_>, err: &PyErr) -> PyResult<String> {
389
391
  let lines: Vec<String> = formatted.extract()?;
390
392
  Ok(lines.concat().trim_end().to_string())
391
393
  }
394
+
395
+ #[cfg(test)]
396
+ mod tests {
397
+ use super::*;
398
+ use std::future::{poll_fn, Future};
399
+ use std::task::Poll;
400
+ use std::time::Duration;
401
+
402
+ #[derive(Clone, Copy)]
403
+ enum Dispatch {
404
+ Streaming,
405
+ Buffered,
406
+ Coalesced,
407
+ }
408
+
409
+ // Polling a dispatch must yield even while another thread owns the GIL:
410
+ // otherwise Python contention blocks the worker that also serves health RPCs.
411
+ fn dispatch_yields_while_gil_is_held(dispatch: Dispatch) {
412
+ Python::initialize();
413
+ let (yielded, worker) = Python::attach(|py| {
414
+ let handler = Arc::new(PythonHandler::new(
415
+ py.None(),
416
+ py.eval(pyo3::ffi::c_str!("lambda *args: []"), None, None)
417
+ .unwrap()
418
+ .unbind(),
419
+ None,
420
+ ));
421
+ let (polled_tx, polled_rx) = std::sync::mpsc::channel();
422
+ let worker = std::thread::spawn(move || {
423
+ let runtime = tokio::runtime::Builder::new_current_thread()
424
+ .build()
425
+ .unwrap();
426
+ runtime.block_on(async move {
427
+ let call = async {
428
+ match dispatch {
429
+ Dispatch::Streaming => {
430
+ let (tx, _rx) = mpsc::channel(1);
431
+ handler
432
+ .call_streaming(
433
+ Vec::new(),
434
+ String::new(),
435
+ HashMap::new(),
436
+ String::new(),
437
+ tx,
438
+ )
439
+ .await
440
+ }
441
+ Dispatch::Buffered => {
442
+ handler
443
+ .call_into_buffer(
444
+ Vec::new(),
445
+ String::new(),
446
+ HashMap::new(),
447
+ String::new(),
448
+ ChunkBuffer::new().into_shared(),
449
+ )
450
+ .await
451
+ }
452
+ Dispatch::Coalesced => {
453
+ handler.call_coalesced(Vec::new()).await.map(|_| ())
454
+ }
455
+ }
456
+ };
457
+ tokio::pin!(call);
458
+ poll_fn(|cx| {
459
+ assert!(call.as_mut().poll(cx).is_pending());
460
+ let _ = polled_tx.send(());
461
+ Poll::Ready(())
462
+ })
463
+ .await;
464
+ call.await.unwrap();
465
+ });
466
+ });
467
+ // No Python bytecode runs here, so CPython cannot periodically release
468
+ // the GIL and accidentally let a blocking attach pass the test.
469
+ let yielded = polled_rx.recv_timeout(Duration::from_secs(5)).is_ok();
470
+ (yielded, worker)
471
+ });
472
+ // Release the GIL before joining so even a regressed implementation exits.
473
+ worker.join().unwrap();
474
+ assert!(
475
+ yielded,
476
+ "dispatch blocked its Tokio worker acquiring the GIL"
477
+ );
478
+ }
479
+
480
+ #[test]
481
+ fn streaming_dispatch_yields_under_gil_contention() {
482
+ dispatch_yields_while_gil_is_held(Dispatch::Streaming);
483
+ }
484
+
485
+ #[test]
486
+ fn buffered_dispatch_yields_under_gil_contention() {
487
+ dispatch_yields_while_gil_is_held(Dispatch::Buffered);
488
+ }
489
+
490
+ #[test]
491
+ fn coalesced_dispatch_yields_under_gil_contention() {
492
+ dispatch_yields_while_gil_is_held(Dispatch::Coalesced);
493
+ }
494
+ }
@@ -1351,7 +1351,7 @@ fn ensure_traceparent(headers: &mut HashMap<String, String>) -> String {
1351
1351
  /// `end`, or `error`) to the call's result stream, updating meta status along
1352
1352
  /// the way.
1353
1353
  async fn execute_and_write(
1354
- handler: &PythonHandler,
1354
+ handler: &Arc<PythonHandler>,
1355
1355
  output: &mut CallOutput,
1356
1356
  work: QueuedCall,
1357
1357
  flush_timeout: Duration,
@@ -0,0 +1 @@
1
+ __version__ = "1.10.8"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalk-remote-call-python
3
- Version: 1.10.7
3
+ Version: 1.10.8
4
4
  Summary: Chalk remote call Python runtime interface client
5
5
  Author: Chalk AI, Inc.
6
6
  Project-URL: Homepage, https://chalk.ai
@@ -14,6 +14,7 @@ chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.tonic.rs
14
14
  chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.utils.v1.rs
15
15
  chalk-remote-call-rs/chalk-remote-call-proto/src/gen/descriptor.bin
16
16
  chalk-remote-call-rs/chalk-remote-call-server/Cargo.toml
17
+ chalk-remote-call-rs/chalk-remote-call-server/build.rs
17
18
  chalk-remote-call-rs/chalk-remote-call-server/src/async_service.rs
18
19
  chalk-remote-call-rs/chalk-remote-call-server/src/coalesce.rs
19
20
  chalk-remote-call-rs/chalk-remote-call-server/src/fnq_client.rs
@@ -1 +0,0 @@
1
- __version__ = "1.10.7"