chalkruntime 3.41.0__tar.gz → 3.41.2__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 (131) hide show
  1. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/PKG-INFO +1 -1
  2. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/convert_chalkpy_underscore.py +2 -0
  3. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/dataframe_resolver_correlation.py +8 -0
  4. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/protograph_deserializer.py +4 -0
  5. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/resolver.py +17 -0
  6. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/bound_invoker.py +8 -0
  7. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/general_bound_invoker.py +23 -2
  8. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/one_to_one_invoker.py +1 -0
  9. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/loader/converter.py +4 -0
  10. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime.egg-info/PKG-INFO +1 -1
  11. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/pyproject.toml +1 -1
  12. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/README.md +0 -0
  13. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/__init__.py +0 -0
  14. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/constants.py +0 -0
  15. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/dataframe/__init__.py +0 -0
  16. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/dataframe/dataframe.py +0 -0
  17. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/dataframe/lazyframe.py +0 -0
  18. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/exc/__init__.py +0 -0
  19. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/exc/failed_argument.py +0 -0
  20. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/exc/resolver_errors.py +0 -0
  21. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/exc/wrapped_resolver_exception.py +0 -0
  22. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/__init__.py +0 -0
  23. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/_sql_source_pickle_patch.py +0 -0
  24. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/chalk_overload.py +0 -0
  25. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/feature.py +0 -0
  26. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/feature_alias.py +0 -0
  27. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/filter_conversion.py +0 -0
  28. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/global_graph.py +0 -0
  29. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/graph.py +0 -0
  30. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/graph_impl.py +0 -0
  31. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/graph_proxy.py +0 -0
  32. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/graph_state.py +0 -0
  33. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/jinja_parser.py +0 -0
  34. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/mat_agg_filter_expression.py +0 -0
  35. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/materializations.py +0 -0
  36. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/materialized_feature_view.py +0 -0
  37. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/maybe_named_collection.py +0 -0
  38. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/named_query.py +0 -0
  39. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/nearest_neighbor.py +0 -0
  40. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/overlay_graph.py +0 -0
  41. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/prompt_service.py +0 -0
  42. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/protograph_serializer.py +0 -0
  43. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/singletons.py +0 -0
  44. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/sklearn_model_parser.py +0 -0
  45. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/source_secrets.py +0 -0
  46. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/stream_resolver.py +0 -0
  47. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/underscore.py +0 -0
  48. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/underscore_codec_info.py +0 -0
  49. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/underscore_operation_registry.py +0 -0
  50. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/graph/variables.py +0 -0
  51. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/heaptrack_launcher.py +0 -0
  52. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/incrementalization/__init__.py +0 -0
  53. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/incrementalization/group_incrementalizer.py +0 -0
  54. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/incrementalization/incrementalizer.py +0 -0
  55. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/__init__.py +0 -0
  56. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/batch_result_collector.py +0 -0
  57. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/bound_invoker_cache.py +0 -0
  58. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/no_arg_scalar_invoker.py +0 -0
  59. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/overlay_features.py +0 -0
  60. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/parse_external_resolver.py +0 -0
  61. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/partition_batch.py +0 -0
  62. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/query_execution_parameters.py +0 -0
  63. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/resolver_args_builder.py +0 -0
  64. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/resolver_input.py +0 -0
  65. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/resolver_input_upload.py +0 -0
  66. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/resolver_output_metadata.py +0 -0
  67. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/resolver_raw_output_parsing.py +0 -0
  68. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/resolver_result.py +0 -0
  69. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/resolver_runner.py +0 -0
  70. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/sample.py +0 -0
  71. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/validator.py +0 -0
  72. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/invoker/vectorized_hasmany_sampler.py +0 -0
  73. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/loader/__init__.py +0 -0
  74. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/loader/importer.py +0 -0
  75. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/memray_launcher.py +0 -0
  76. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/metadata.py +0 -0
  77. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/py.typed +0 -0
  78. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/server/__init__.py +0 -0
  79. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/server/branch_model_endpoint_config.py +0 -0
  80. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/server/config.py +0 -0
  81. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/server/entrypoint.py +0 -0
  82. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/server/env_helper.py +0 -0
  83. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/server/remote_python_function_registry_client.py +0 -0
  84. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/server/server_context_snapshot.py +0 -0
  85. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/server/service.py +0 -0
  86. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/sql_rewriter/__init__.py +0 -0
  87. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/sql_rewriter/composed_rewriter.py +0 -0
  88. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/sql_rewriter/contextual_query_rewriter.py +0 -0
  89. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/sql_rewriter/filter_injection_site.py +0 -0
  90. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/sql_rewriter/filter_query_rewriter.py +0 -0
  91. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/sql_rewriter/identity_rewriter.py +0 -0
  92. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/sql_rewriter/query_rewriter.py +0 -0
  93. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/sql_rewriter/query_rewriter_helper.py +0 -0
  94. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/__init__.py +0 -0
  95. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/converter_utils.py +0 -0
  96. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/exc.py +0 -0
  97. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/message_parsing.py +0 -0
  98. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/resolver_utils.py +0 -0
  99. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/streaming_invoker_kernel/__init__.py +0 -0
  100. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/streaming_invoker_kernel/local_streaming_invoker_kernel.py +0 -0
  101. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/types.py +0 -0
  102. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/streaming/window_keys.py +0 -0
  103. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/__init__.py +0 -0
  104. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/async_helpers.py +0 -0
  105. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/contextvars.py +0 -0
  106. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/datadog.py +0 -0
  107. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/internal_pl_utils.py +0 -0
  108. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/posix_file_lock.py +0 -0
  109. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/proto_bytes_cache.py +0 -0
  110. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/pyarrow_utils.py +0 -0
  111. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/tracing.py +0 -0
  112. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/utils/viztracer_profiling.py +0 -0
  113. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime/valgrind_launcher.py +0 -0
  114. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime.egg-info/SOURCES.txt +0 -0
  115. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime.egg-info/dependency_links.txt +0 -0
  116. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime.egg-info/requires.txt +0 -0
  117. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/chalkruntime.egg-info/top_level.txt +0 -0
  118. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/setup.cfg +0 -0
  119. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/setup.py +0 -0
  120. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_branch_model_endpoint_config.py +0 -0
  121. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_captured_global_function_refs.py +0 -0
  122. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_datadog.py +0 -0
  123. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_feature_aliases.py +0 -0
  124. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_graph_cache.py +0 -0
  125. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_internal_pl_utils.py +0 -0
  126. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_mat_agg_filter_expressions.py +0 -0
  127. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_mat_agg_projection_expressions.py +0 -0
  128. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_materialized_feature_view.py +0 -0
  129. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_posix_file_lock.py +0 -0
  130. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_pyarrow_utils.py +0 -0
  131. {chalkruntime-3.41.0 → chalkruntime-3.41.2}/tests/test_server_context_snapshot.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalkruntime
3
- Version: 3.41.0
3
+ Version: 3.41.2
4
4
  Summary: Runtime support library for Chalk AI
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -3050,6 +3050,7 @@ def underscore_to_online_resolver(
3050
3050
  incremental_settings=None,
3051
3051
  is_externally_defined=False,
3052
3052
  output_row_order=None,
3053
+ max_batch_size=None,
3053
3054
  venv=None,
3054
3055
  postprocessing=None,
3055
3056
  )
@@ -3107,6 +3108,7 @@ def underscore_to_offline_resolver(
3107
3108
  incremental_settings=None,
3108
3109
  is_externally_defined=False,
3109
3110
  output_row_order=None,
3111
+ max_batch_size=None,
3110
3112
  venv=None,
3111
3113
  postprocessing=None,
3112
3114
  )
@@ -27,6 +27,14 @@ def dataframe_resolver_correlation_mode(resolver: ResolverParsed) -> DataFrameRe
27
27
  output_has_index = dataframe_type_has_index(resolver.unique_df_output, resolver.graph)
28
28
 
29
29
  if not indexed_inputs and not output_has_index:
30
+ if resolver.max_batch_size is not None:
31
+ # Legacy positional correlation cannot safely reassemble chunked outputs if the
32
+ # resolver filters or reorders rows, so chunking requires Index correlation.
33
+ raise ValueError(
34
+ f"Resolver '{resolver.fqn}' sets max_batch_size={resolver.max_batch_size}, but max_batch_size requires"
35
+ + " Index row correlation. Declare Index in the resolver's input DataFrame and output DataFrame, or"
36
+ + " remove max_batch_size."
37
+ )
30
38
  return DataFrameResolverCorrelationMode.LEGACY
31
39
 
32
40
  if len(indexed_inputs) != 1 or not output_has_index:
@@ -2294,6 +2294,7 @@ class FromProtoConverter:
2294
2294
  is_externally_defined=False,
2295
2295
  feature_expressions=feature_expressions,
2296
2296
  output_row_order=None,
2297
+ max_batch_size=None,
2297
2298
  venv=None,
2298
2299
  stream_sink_config=sink_config,
2299
2300
  postprocessing=None,
@@ -2487,6 +2488,8 @@ class FromProtoConverter:
2487
2488
  if output_row_order not in (None, "one-to-one"):
2488
2489
  raise ValueError(f"output_row_order must be either None or 'one-to-one', received {r.output_row_order}")
2489
2490
 
2491
+ max_batch_size = r.max_batch_size if r.HasField("max_batch_size") and r.max_batch_size > 0 else None
2492
+
2490
2493
  postprocessing_expr: Underscore | None = None
2491
2494
  if r.WhichOneof("postprocessing") == "underscore_expr":
2492
2495
  if not r.HasField("sql_settings"):
@@ -2544,6 +2547,7 @@ class FromProtoConverter:
2544
2547
  else None,
2545
2548
  is_externally_defined=is_externally_defined,
2546
2549
  output_row_order=output_row_order, # ty:ignore[invalid-argument-type]
2550
+ max_batch_size=max_batch_size,
2547
2551
  venv=r.venv if r.HasField("venv") else None,
2548
2552
  postprocessing=postprocessing_expr,
2549
2553
  )
@@ -301,6 +301,12 @@ class ResolverParsed:
301
301
  If "one-to-one", verify that this is a DF -> DF resolver, and treat it as a bulk scalar operation.
302
302
  """
303
303
 
304
+ max_batch_size: int | None = dataclasses.field(compare=False, repr=False)
305
+ """
306
+ Max rows per invocation for Index-correlated DF -> DF resolvers; the invoker slices the
307
+ input and invokes the resolver once per chunk. None = unlimited (single invocation).
308
+ """
309
+
304
310
  venv: str | None = dataclasses.field(compare=False, repr=False)
305
311
  """
306
312
  The venv that the resolver should be run in.
@@ -574,6 +580,17 @@ class ResolverParsed:
574
580
  f"Resolver '{self.fqn}' has output_row_order='one-to-one', but it does not take in and return the pkey column."
575
581
  )
576
582
 
583
+ if self.max_batch_size is not None:
584
+ if self.max_batch_size < 1:
585
+ raise ValueError(
586
+ f"Resolver '{self.fqn}' has max_batch_size={self.max_batch_size}, but it must be >= 1."
587
+ )
588
+ if not self.input_is_df or not self.output_is_df:
589
+ raise ValueError(
590
+ f"Resolver '{self.fqn}' has max_batch_size={self.max_batch_size}, but max_batch_size only applies"
591
+ + " to DataFrame -> DataFrame resolvers."
592
+ )
593
+
577
594
  inputs_include_now_pseudofeature: bool = dataclasses.field(init=False, compare=False, repr=False)
578
595
 
579
596
  def get_fn(self):
@@ -71,6 +71,8 @@ class PlanTimeInvokerConfig:
71
71
  # should correspond to the planner option value
72
72
  allow_planner_postponed_has_many_sampling: bool
73
73
  invoker_uses_strict_timeouts: bool
74
+ # should correspond to the planner option value; None or <=0 = unlimited
75
+ df_resolver_default_max_batch_size: int | None
74
76
 
75
77
  def __init__(
76
78
  self,
@@ -97,6 +99,7 @@ class PlanTimeInvokerConfig:
97
99
  oom_max_num_inputs_per_hm_sample: int,
98
100
  allow_planner_postponed_has_many_sampling: bool,
99
101
  invoker_uses_strict_timeouts: bool,
102
+ df_resolver_default_max_batch_size: int | None,
100
103
  _freeze: bool = True,
101
104
  ):
102
105
  super().__init__()
@@ -123,6 +126,7 @@ class PlanTimeInvokerConfig:
123
126
  self.oom_max_num_inputs_per_hm_sample = int(oom_max_num_inputs_per_hm_sample)
124
127
  self.allow_planner_postponed_has_many_sampling = allow_planner_postponed_has_many_sampling
125
128
  self.invoker_uses_strict_timeouts = invoker_uses_strict_timeouts
129
+ self.df_resolver_default_max_batch_size = _optional_int(df_resolver_default_max_batch_size)
126
130
  self._frozen = _freeze
127
131
 
128
132
  def __setattr__(self, name: str, value: Any) -> None:
@@ -154,6 +158,7 @@ class PlanTimeInvokerConfig:
154
158
  "oom_max_num_inputs_per_hm_sample": self.oom_max_num_inputs_per_hm_sample,
155
159
  "allow_planner_postponed_has_many_sampling": self.allow_planner_postponed_has_many_sampling,
156
160
  "invoker_uses_strict_timeouts": self.invoker_uses_strict_timeouts,
161
+ "df_resolver_default_max_batch_size": self.df_resolver_default_max_batch_size,
157
162
  }
158
163
  return _drop_none(data) if exclude_none else data
159
164
 
@@ -209,6 +214,7 @@ class InvokerConfig(PlanTimeInvokerConfig):
209
214
  oom_max_num_inputs_per_hm_sample: int,
210
215
  allow_planner_postponed_has_many_sampling: bool,
211
216
  invoker_uses_strict_timeouts: bool,
217
+ df_resolver_default_max_batch_size: int | None,
212
218
  operation_id: str,
213
219
  correlation_id: str | None = None,
214
220
  query_context: ContextJsonDict | None = None,
@@ -236,6 +242,7 @@ class InvokerConfig(PlanTimeInvokerConfig):
236
242
  oom_max_num_inputs_per_hm_sample=oom_max_num_inputs_per_hm_sample,
237
243
  allow_planner_postponed_has_many_sampling=allow_planner_postponed_has_many_sampling,
238
244
  invoker_uses_strict_timeouts=invoker_uses_strict_timeouts,
245
+ df_resolver_default_max_batch_size=df_resolver_default_max_batch_size,
239
246
  _freeze=False,
240
247
  )
241
248
  self.operation_id = operation_id
@@ -267,6 +274,7 @@ class InvokerConfig(PlanTimeInvokerConfig):
267
274
  "oom_max_num_inputs_per_hm_sample": self.oom_max_num_inputs_per_hm_sample,
268
275
  "allow_planner_postponed_has_many_sampling": self.allow_planner_postponed_has_many_sampling,
269
276
  "invoker_uses_strict_timeouts": self.invoker_uses_strict_timeouts,
277
+ "df_resolver_default_max_batch_size": self.df_resolver_default_max_batch_size,
270
278
  "operation_id": self.operation_id,
271
279
  "correlation_id": self.correlation_id,
272
280
  "query_context": self.query_context,
@@ -682,8 +682,29 @@ class GeneralBoundInvoker(BoundInvokerProtocol):
682
682
  "There should not be any scalarish features if the resolver is dataframe-taking or Now -> DataFrame"
683
683
  )
684
684
  assert batch.observed_at_fallback is not None
685
- # Resolver takes only DFs or nothing. Should be called once.
686
- yield arg_constructor(batch.observed_at_fallback, table_feature_to_results)
685
+ sample = arg_constructor(batch.observed_at_fallback, table_feature_to_results)
686
+ resolver_args = sample.resolver_args_or_error
687
+ max_batch_size = 0
688
+ if self._resolver.has_index_correlated_df_io and isinstance(resolver_args, tuple):
689
+ # Chunking is only safe under Index correlation: the operator joins outputs back to
690
+ # inputs by the Index column, so N invocations concatenate without positional
691
+ # assumptions. Legacy (hstack) correlation must keep the single invocation.
692
+ max_batch_size = self._resolver.max_batch_size or config.df_resolver_default_max_batch_size or 0
693
+ if max_batch_size > 0 and isinstance(resolver_args, tuple) and len(resolver_args[0]) > max_batch_size:
694
+ # has_index_correlated_df_io implies exactly one DataFrame input. Each chunk runs as
695
+ # its own invocation: the resolver timeout applies per chunk, and a chunk that raises
696
+ # produces a ChalkError for that chunk while the remaining chunks still emit data.
697
+ (df,) = resolver_args
698
+ for offset in range(0, len(df), max_batch_size):
699
+ yield Sample(
700
+ index=None,
701
+ pkey=None,
702
+ execution_ts=sample.execution_ts,
703
+ resolver_args_or_error=(df.slice(offset, max_batch_size),),
704
+ )
705
+ else:
706
+ # Resolver takes only DFs or nothing. Should be called once.
707
+ yield sample
687
708
  else:
688
709
  assert batch.scalarish_features is not None
689
710
  assert self._resolver.cron_filter is None, "Resolvers with filters are not supported"
@@ -663,6 +663,7 @@ class ParallelResolverInvoker(BoundInvokerProtocol):
663
663
  incremental_settings=None,
664
664
  is_externally_defined=False,
665
665
  output_row_order=None,
666
+ max_batch_size=None,
666
667
  venv=None,
667
668
  postprocessing=None,
668
669
  )
@@ -1105,6 +1105,7 @@ class RegistryConverter:
1105
1105
  is_externally_defined=False,
1106
1106
  feature_expressions=parsed_feature_expressions,
1107
1107
  output_row_order=None,
1108
+ max_batch_size=None,
1108
1109
  venv=None,
1109
1110
  stream_sink_config=sink_config,
1110
1111
  postprocessing=r.postprocessing,
@@ -1167,6 +1168,7 @@ class RegistryConverter:
1167
1168
  incremental_settings=None,
1168
1169
  is_externally_defined=False,
1169
1170
  output_row_order=None,
1171
+ max_batch_size=None,
1170
1172
  venv=None,
1171
1173
  postprocessing=r.postprocessing,
1172
1174
  runtime_contract=r.runtime_contract,
@@ -1267,6 +1269,7 @@ class RegistryConverter:
1267
1269
  incremental_settings=self._convert_incremental_config(r.incremental_settings),
1268
1270
  is_externally_defined=False,
1269
1271
  output_row_order=r.output_row_order, # pyright: ignore[reportArgumentType]
1272
+ max_batch_size=r.max_batch_size,
1270
1273
  venv=r.venv,
1271
1274
  postprocessing=r.postprocessing,
1272
1275
  handle_duplicate_outputs=cast(HandleDuplicateOutputs | None, r.handle_duplicate_outputs or None),
@@ -1333,6 +1336,7 @@ class RegistryConverter:
1333
1336
  incremental_settings=self._convert_incremental_config(r.incremental_settings),
1334
1337
  is_externally_defined=False,
1335
1338
  output_row_order=r.output_row_order, # pyright: ignore[reportArgumentType]
1339
+ max_batch_size=r.max_batch_size,
1336
1340
  venv=r.venv,
1337
1341
  postprocessing=r.postprocessing,
1338
1342
  handle_duplicate_outputs=cast(HandleDuplicateOutputs | None, r.handle_duplicate_outputs or None),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalkruntime
3
- Version: 3.41.0
3
+ Version: 3.41.2
4
4
  Summary: Runtime support library for Chalk AI
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -42,7 +42,7 @@ name = "chalkruntime"
42
42
  description = "Runtime support library for Chalk AI"
43
43
  readme = "README.md"
44
44
  requires-python = ">=3.10"
45
- version = "3.41.0"
45
+ version = "3.41.2"
46
46
 
47
47
 
48
48
  [tool.deptry]
File without changes
File without changes
File without changes