chalk-remote-call-python 1.6.1__tar.gz → 1.6.3__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 (63) hide show
  1. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/PKG-INFO +5 -1
  2. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-server/src/python_bridge.rs +35 -8
  3. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-server/src/service.rs +7 -13
  4. chalk_remote_call_python-1.6.3/chalk_remote_call/_version.py +1 -0
  5. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/servicer.py +30 -6
  6. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call_python.egg-info/PKG-INFO +5 -1
  7. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call_python.egg-info/requires.txt +5 -0
  8. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/pyproject.toml +5 -0
  9. chalk_remote_call_python-1.6.1/chalk_remote_call/_version.py +0 -1
  10. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/MANIFEST.in +0 -0
  11. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/README.md +0 -0
  12. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/Cargo.lock +0 -0
  13. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/Cargo.toml +0 -0
  14. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-proto/Cargo.toml +0 -0
  15. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.auth.v1.rs +0 -0
  16. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.common.v1.rs +0 -0
  17. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.rs +0 -0
  18. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.tonic.rs +0 -0
  19. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.utils.v1.rs +0 -0
  20. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/descriptor.bin +0 -0
  21. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-proto/src/lib.rs +0 -0
  22. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-server/Cargo.toml +0 -0
  23. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-server/src/coalesce.rs +0 -0
  24. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-server/src/lib.rs +0 -0
  25. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/chalk-remote-call-server/src/server.rs +0 -0
  26. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk-remote-call-rs/rust-toolchain.toml +0 -0
  27. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/__init__.py +0 -0
  28. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/__main__.py +0 -0
  29. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/__init__.py +0 -0
  30. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/__init__.py +0 -0
  31. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/auth/__init__.py +0 -0
  32. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/auth/v1/__init__.py +0 -0
  33. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2.py +0 -0
  34. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2_grpc.py +0 -0
  35. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/common/__init__.py +0 -0
  36. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/common/v1/__init__.py +0 -0
  37. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2.py +0 -0
  38. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2_grpc.py +0 -0
  39. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/runtime/__init__.py +0 -0
  40. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/runtime/v1/__init__.py +0 -0
  41. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2.py +0 -0
  42. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2_grpc.py +0 -0
  43. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/utils/__init__.py +0 -0
  44. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/utils/v1/__init__.py +0 -0
  45. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2.py +0 -0
  46. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2_grpc.py +0 -0
  47. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2.py +0 -0
  48. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2_grpc.py +0 -0
  49. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2.py +0 -0
  50. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2_grpc.py +0 -0
  51. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/_native.pyi +0 -0
  52. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/arrow_utils.py +0 -0
  53. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/cli.py +0 -0
  54. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/handler_loader.py +0 -0
  55. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/input_transform.py +0 -0
  56. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/server.py +0 -0
  57. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call/tracing.py +0 -0
  58. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call_python.egg-info/SOURCES.txt +0 -0
  59. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call_python.egg-info/dependency_links.txt +0 -0
  60. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call_python.egg-info/entry_points.txt +0 -0
  61. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/chalk_remote_call_python.egg-info/top_level.txt +0 -0
  62. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/setup.cfg +0 -0
  63. {chalk_remote_call_python-1.6.1 → chalk_remote_call_python-1.6.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalk-remote-call-python
3
- Version: 1.6.1
3
+ Version: 1.6.3
4
4
  Summary: Chalk remote call Python runtime interface client
5
5
  Author: Chalk AI, Inc.
6
6
  Project-URL: Homepage, https://chalk.ai
@@ -31,6 +31,10 @@ Requires-Dist: grpcio-health-checking>=1.60.0; extra == "dev"
31
31
  Requires-Dist: grpcio-reflection>=1.60.0; extra == "dev"
32
32
  Requires-Dist: protobuf>=4.25.0; extra == "dev"
33
33
  Requires-Dist: grpcio-tools>=1.60.0; extra == "dev"
34
+ Provides-Extra: tracing
35
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == "tracing"
36
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == "tracing"
37
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20.0; extra == "tracing"
34
38
 
35
39
  # chalk-remote-call-python
36
40
 
@@ -1,7 +1,10 @@
1
1
  use std::collections::HashMap;
2
2
 
3
+ use chalk_remote_call_proto::chalk::runtime::v1::CallFunctionResponse;
3
4
  use pyo3::prelude::*;
4
5
  use pyo3::types::{PyBytes, PyDict, PyList};
6
+ use tokio::sync::mpsc;
7
+ use tonic::Status;
5
8
 
6
9
  /// Holds references to the Python handler and bridge function.
7
10
  pub struct PythonHandler {
@@ -34,29 +37,35 @@ impl PythonHandler {
34
37
  }
35
38
  }
36
39
 
37
- /// Non-batched: one caller per invocation. Dispatches to `process_batches`.
38
- ///
39
- /// Returns a list of IPC-encoded response chunks — multiple when the
40
- /// handler is a generator, one otherwise.
41
- pub async fn call(
40
+ /// Non-batched streaming dispatch. Calls `process_batches(..., emit)` so
41
+ /// generator results are sent to the gRPC stream as each yield is encoded.
42
+ pub async fn call_streaming(
42
43
  &self,
43
44
  ipc_bytes: Vec<u8>,
44
45
  function_name: String,
45
46
  metadata: HashMap<String, String>,
46
47
  peer: String,
47
- ) -> Result<Vec<Vec<u8>>, PythonError> {
48
+ response_tx: mpsc::Sender<Result<CallFunctionResponse, Status>>,
49
+ ) -> Result<(), PythonError> {
48
50
  let (handler, process_fn) =
49
51
  Python::attach(|py| (self.handler.clone_ref(py), self.process_fn.clone_ref(py)));
50
52
  let arg_names = self.arg_names.clone();
51
53
 
52
54
  tokio::task::spawn_blocking(move || {
53
- Python::attach(|py| -> Result<Vec<Vec<u8>>, PythonError> {
55
+ Python::attach(|py| -> Result<(), PythonError> {
54
56
  let py_bytes = PyBytes::new(py, &ipc_bytes).into_any().unbind();
55
57
  let py_ctx = build_context(py, &function_name, &metadata, &peer)?
56
58
  .into_any()
57
59
  .unbind();
58
60
  let py_arg_names = build_arg_names(py, arg_names.as_deref())?;
59
- invoke_process_fn(py, &process_fn, &handler, py_bytes, py_arg_names, py_ctx)
61
+ let emitter = Py::new(py, ChunkEmitter { response_tx })
62
+ .map_err(|e| into_python_error(py, e))?
63
+ .into_any();
64
+
65
+ process_fn
66
+ .call1(py, (py_bytes, handler, py_arg_names, py_ctx, emitter))
67
+ .map_err(|e| into_python_error(py, e))?;
68
+ Ok(())
60
69
  })
61
70
  })
62
71
  .await
@@ -104,6 +113,24 @@ impl PythonHandler {
104
113
 
105
114
  // ---- Shared helpers -------------------------------------------------------
106
115
 
116
+ #[pyclass]
117
+ struct ChunkEmitter {
118
+ response_tx: mpsc::Sender<Result<CallFunctionResponse, Status>>,
119
+ }
120
+
121
+ #[pymethods]
122
+ impl ChunkEmitter {
123
+ fn __call__(&self, chunk: &Bound<'_, PyBytes>) -> PyResult<()> {
124
+ let msg = CallFunctionResponse {
125
+ feather_stream: chunk.as_bytes().to_vec().into(),
126
+ };
127
+ self.response_tx
128
+ .blocking_send(Ok(msg))
129
+ .map_err(|_| pyo3::exceptions::PyRuntimeError::new_err("client disconnected"))?;
130
+ Ok(())
131
+ }
132
+ }
133
+
107
134
  /// Build a `{"function_name": str, "peer": str, "metadata": dict}` context dict for one caller.
108
135
  fn build_context<'py>(
109
136
  py: Python<'py>,
@@ -91,21 +91,15 @@ impl RemoteCallService for RemoteCallServiceImpl {
91
91
  // Single-request path.
92
92
  let handler = self.python_handler.clone();
93
93
  tokio::spawn(async move {
94
- match handler.call(all_bytes, function_name, metadata, peer).await {
95
- Ok(response_chunks) => {
96
- for chunk in response_chunks {
97
- let msg = CallFunctionResponse {
98
- feather_stream: chunk.into(),
99
- };
100
- if tx.send(Ok(msg)).await.is_err() {
101
- // Client disconnected
102
- break;
103
- }
104
- }
105
- }
94
+ let error_tx = tx.clone();
95
+ match handler
96
+ .call_streaming(all_bytes, function_name, metadata, peer, tx)
97
+ .await
98
+ {
99
+ Ok(()) => {}
106
100
  Err(e) => {
107
101
  error!("Python handler error: {}", e);
108
- let _ = tx
102
+ let _ = error_tx
109
103
  .send(Err(Status::unknown(format!(
110
104
  "Exception raised during handler execution: {e}"
111
105
  ))))
@@ -0,0 +1 @@
1
+ __version__ = "1.6.3"
@@ -158,11 +158,22 @@ def _collect_async_gen(agen) -> list:
158
158
  return _run_async(_collect())
159
159
 
160
160
 
161
+ def _drain_async_gen(agen, emit: Callable[[bytes], None]) -> None:
162
+ """Drain an async generator and emit each encoded item immediately."""
163
+
164
+ async def _drain():
165
+ async for item in agen:
166
+ emit(encode_record_batch(_coerce_to_record_batch(item)))
167
+
168
+ _run_async(_drain())
169
+
170
+
161
171
  def process_batches(
162
172
  ipc_bytes: bytes,
163
173
  handler: Callable[..., Any],
164
174
  arg_names: list[str] | None,
165
175
  context_metadata: dict[str, Any],
176
+ emit: Callable[[bytes], None] | None = None,
166
177
  ) -> list[bytes]:
167
178
  """Bridge function called from Rust via PyO3.
168
179
 
@@ -170,9 +181,18 @@ def process_batches(
170
181
  coerces the result, and encodes the response.
171
182
 
172
183
  Returns a list of IPC-encoded response bytes (one per input batch).
184
+ When ``emit`` is provided, each encoded response is emitted immediately and
185
+ the returned list is empty.
173
186
  """
174
187
  batches = decode_ipc_stream(ipc_bytes)
175
188
  results = []
189
+
190
+ def append_or_emit(chunk: bytes) -> None:
191
+ if emit is None:
192
+ results.append(chunk)
193
+ else:
194
+ emit(chunk)
195
+
176
196
  for batch in batches:
177
197
  try:
178
198
  event = transform(batch, arg_names)
@@ -193,15 +213,19 @@ def process_batches(
193
213
  # Sync generator: encode each yielded value as a separate chunk.
194
214
  for item in result:
195
215
  result_batch = _coerce_to_record_batch(item)
196
- results.append(encode_record_batch(result_batch))
216
+ append_or_emit(encode_record_batch(result_batch))
197
217
  elif inspect.isasyncgen(result):
198
- # Async generator: collect items and encode each as a separate chunk.
199
- for item in _collect_async_gen(result):
200
- result_batch = _coerce_to_record_batch(item)
201
- results.append(encode_record_batch(result_batch))
218
+ # Async generator: stream when possible, otherwise preserve
219
+ # the existing list-returning bridge contract.
220
+ if emit is not None:
221
+ _drain_async_gen(result, emit)
222
+ else:
223
+ for item in _collect_async_gen(result):
224
+ result_batch = _coerce_to_record_batch(item)
225
+ results.append(encode_record_batch(result_batch))
202
226
  else:
203
227
  result_batch = _coerce_to_record_batch(result)
204
- results.append(encode_record_batch(result_batch))
228
+ append_or_emit(encode_record_batch(result_batch))
205
229
  except Exception as e:
206
230
  raise RuntimeError(f"Failed to encode response: {e}") from e
207
231
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalk-remote-call-python
3
- Version: 1.6.1
3
+ Version: 1.6.3
4
4
  Summary: Chalk remote call Python runtime interface client
5
5
  Author: Chalk AI, Inc.
6
6
  Project-URL: Homepage, https://chalk.ai
@@ -31,6 +31,10 @@ Requires-Dist: grpcio-health-checking>=1.60.0; extra == "dev"
31
31
  Requires-Dist: grpcio-reflection>=1.60.0; extra == "dev"
32
32
  Requires-Dist: protobuf>=4.25.0; extra == "dev"
33
33
  Requires-Dist: grpcio-tools>=1.60.0; extra == "dev"
34
+ Provides-Extra: tracing
35
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == "tracing"
36
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == "tracing"
37
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20.0; extra == "tracing"
34
38
 
35
39
  # chalk-remote-call-python
36
40
 
@@ -9,3 +9,8 @@ grpcio-health-checking>=1.60.0
9
9
  grpcio-reflection>=1.60.0
10
10
  protobuf>=4.25.0
11
11
  grpcio-tools>=1.60.0
12
+
13
+ [tracing]
14
+ opentelemetry-api>=1.20.0
15
+ opentelemetry-sdk>=1.20.0
16
+ opentelemetry-exporter-otlp-proto-grpc>=1.20.0
@@ -44,6 +44,11 @@ dev = [
44
44
  "protobuf>=4.25.0",
45
45
  "grpcio-tools>=1.60.0",
46
46
  ]
47
+ tracing = [
48
+ "opentelemetry-api>=1.20.0",
49
+ "opentelemetry-sdk>=1.20.0",
50
+ "opentelemetry-exporter-otlp-proto-grpc>=1.20.0",
51
+ ]
47
52
 
48
53
  [project.urls]
49
54
  Homepage = "https://chalk.ai"
@@ -1 +0,0 @@
1
- __version__ = "1.6.1"