chalkpy 2.90.1__py3-none-any.whl → 2.95.3__py3-none-any.whl

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 (202) hide show
  1. chalk/__init__.py +2 -1
  2. chalk/_gen/chalk/arrow/v1/arrow_pb2.py +7 -5
  3. chalk/_gen/chalk/arrow/v1/arrow_pb2.pyi +6 -0
  4. chalk/_gen/chalk/artifacts/v1/chart_pb2.py +16 -16
  5. chalk/_gen/chalk/artifacts/v1/chart_pb2.pyi +4 -0
  6. chalk/_gen/chalk/artifacts/v1/cron_query_pb2.py +8 -7
  7. chalk/_gen/chalk/artifacts/v1/cron_query_pb2.pyi +5 -0
  8. chalk/_gen/chalk/common/v1/offline_query_pb2.py +17 -15
  9. chalk/_gen/chalk/common/v1/offline_query_pb2.pyi +25 -0
  10. chalk/_gen/chalk/common/v1/script_task_pb2.py +3 -3
  11. chalk/_gen/chalk/common/v1/script_task_pb2.pyi +2 -0
  12. chalk/_gen/chalk/dataframe/__init__.py +0 -0
  13. chalk/_gen/chalk/dataframe/v1/__init__.py +0 -0
  14. chalk/_gen/chalk/dataframe/v1/dataframe_pb2.py +48 -0
  15. chalk/_gen/chalk/dataframe/v1/dataframe_pb2.pyi +123 -0
  16. chalk/_gen/chalk/dataframe/v1/dataframe_pb2_grpc.py +4 -0
  17. chalk/_gen/chalk/dataframe/v1/dataframe_pb2_grpc.pyi +4 -0
  18. chalk/_gen/chalk/graph/v1/graph_pb2.py +150 -149
  19. chalk/_gen/chalk/graph/v1/graph_pb2.pyi +25 -0
  20. chalk/_gen/chalk/graph/v1/sources_pb2.py +94 -84
  21. chalk/_gen/chalk/graph/v1/sources_pb2.pyi +56 -0
  22. chalk/_gen/chalk/kubernetes/v1/horizontalpodautoscaler_pb2.py +79 -0
  23. chalk/_gen/chalk/kubernetes/v1/horizontalpodautoscaler_pb2.pyi +377 -0
  24. chalk/_gen/chalk/kubernetes/v1/horizontalpodautoscaler_pb2_grpc.py +4 -0
  25. chalk/_gen/chalk/kubernetes/v1/horizontalpodautoscaler_pb2_grpc.pyi +4 -0
  26. chalk/_gen/chalk/kubernetes/v1/scaledobject_pb2.py +43 -7
  27. chalk/_gen/chalk/kubernetes/v1/scaledobject_pb2.pyi +252 -2
  28. chalk/_gen/chalk/protosql/v1/sql_service_pb2.py +54 -27
  29. chalk/_gen/chalk/protosql/v1/sql_service_pb2.pyi +131 -3
  30. chalk/_gen/chalk/protosql/v1/sql_service_pb2_grpc.py +45 -0
  31. chalk/_gen/chalk/protosql/v1/sql_service_pb2_grpc.pyi +14 -0
  32. chalk/_gen/chalk/python/v1/types_pb2.py +14 -14
  33. chalk/_gen/chalk/python/v1/types_pb2.pyi +8 -0
  34. chalk/_gen/chalk/server/v1/benchmark_pb2.py +76 -0
  35. chalk/_gen/chalk/server/v1/benchmark_pb2.pyi +156 -0
  36. chalk/_gen/chalk/server/v1/benchmark_pb2_grpc.py +258 -0
  37. chalk/_gen/chalk/server/v1/benchmark_pb2_grpc.pyi +84 -0
  38. chalk/_gen/chalk/server/v1/billing_pb2.py +40 -38
  39. chalk/_gen/chalk/server/v1/billing_pb2.pyi +17 -1
  40. chalk/_gen/chalk/server/v1/branches_pb2.py +45 -0
  41. chalk/_gen/chalk/server/v1/branches_pb2.pyi +80 -0
  42. chalk/_gen/chalk/server/v1/branches_pb2_grpc.pyi +36 -0
  43. chalk/_gen/chalk/server/v1/builder_pb2.py +358 -288
  44. chalk/_gen/chalk/server/v1/builder_pb2.pyi +360 -10
  45. chalk/_gen/chalk/server/v1/builder_pb2_grpc.py +225 -0
  46. chalk/_gen/chalk/server/v1/builder_pb2_grpc.pyi +60 -0
  47. chalk/_gen/chalk/server/v1/chart_pb2.py +10 -10
  48. chalk/_gen/chalk/server/v1/chart_pb2.pyi +18 -2
  49. chalk/_gen/chalk/server/v1/clickhouse_pb2.py +42 -0
  50. chalk/_gen/chalk/server/v1/clickhouse_pb2.pyi +17 -0
  51. chalk/_gen/chalk/server/v1/clickhouse_pb2_grpc.py +78 -0
  52. chalk/_gen/chalk/server/v1/clickhouse_pb2_grpc.pyi +38 -0
  53. chalk/_gen/chalk/server/v1/cloud_components_pb2.py +141 -119
  54. chalk/_gen/chalk/server/v1/cloud_components_pb2.pyi +106 -4
  55. chalk/_gen/chalk/server/v1/cloud_components_pb2_grpc.py +45 -0
  56. chalk/_gen/chalk/server/v1/cloud_components_pb2_grpc.pyi +12 -0
  57. chalk/_gen/chalk/server/v1/cloud_credentials_pb2.py +11 -3
  58. chalk/_gen/chalk/server/v1/cloud_credentials_pb2.pyi +20 -0
  59. chalk/_gen/chalk/server/v1/cloud_credentials_pb2_grpc.py +45 -0
  60. chalk/_gen/chalk/server/v1/cloud_credentials_pb2_grpc.pyi +12 -0
  61. chalk/_gen/chalk/server/v1/dataplanejobqueue_pb2.py +52 -38
  62. chalk/_gen/chalk/server/v1/dataplanejobqueue_pb2.pyi +62 -1
  63. chalk/_gen/chalk/server/v1/dataplanejobqueue_pb2_grpc.py +90 -0
  64. chalk/_gen/chalk/server/v1/dataplanejobqueue_pb2_grpc.pyi +24 -0
  65. chalk/_gen/chalk/server/v1/dataplaneworkflows_pb2.py +90 -0
  66. chalk/_gen/chalk/server/v1/dataplaneworkflows_pb2.pyi +264 -0
  67. chalk/_gen/chalk/server/v1/dataplaneworkflows_pb2_grpc.py +170 -0
  68. chalk/_gen/chalk/server/v1/dataplaneworkflows_pb2_grpc.pyi +62 -0
  69. chalk/_gen/chalk/server/v1/deploy_pb2.py +9 -3
  70. chalk/_gen/chalk/server/v1/deploy_pb2.pyi +12 -0
  71. chalk/_gen/chalk/server/v1/deploy_pb2_grpc.py +45 -0
  72. chalk/_gen/chalk/server/v1/deploy_pb2_grpc.pyi +12 -0
  73. chalk/_gen/chalk/server/v1/deployment_pb2.py +6 -6
  74. chalk/_gen/chalk/server/v1/deployment_pb2.pyi +20 -0
  75. chalk/_gen/chalk/server/v1/environment_pb2.py +14 -12
  76. chalk/_gen/chalk/server/v1/environment_pb2.pyi +19 -0
  77. chalk/_gen/chalk/server/v1/eventbus_pb2.py +4 -2
  78. chalk/_gen/chalk/server/v1/files_pb2.py +65 -0
  79. chalk/_gen/chalk/server/v1/files_pb2.pyi +167 -0
  80. chalk/_gen/chalk/server/v1/files_pb2_grpc.py +4 -0
  81. chalk/_gen/chalk/server/v1/files_pb2_grpc.pyi +4 -0
  82. chalk/_gen/chalk/server/v1/graph_pb2.py +38 -26
  83. chalk/_gen/chalk/server/v1/graph_pb2.pyi +58 -0
  84. chalk/_gen/chalk/server/v1/graph_pb2_grpc.py +47 -0
  85. chalk/_gen/chalk/server/v1/graph_pb2_grpc.pyi +18 -0
  86. chalk/_gen/chalk/server/v1/incident_pb2.py +23 -21
  87. chalk/_gen/chalk/server/v1/incident_pb2.pyi +15 -1
  88. chalk/_gen/chalk/server/v1/indexing_job_pb2.py +44 -0
  89. chalk/_gen/chalk/server/v1/indexing_job_pb2.pyi +38 -0
  90. chalk/_gen/chalk/server/v1/indexing_job_pb2_grpc.py +78 -0
  91. chalk/_gen/chalk/server/v1/indexing_job_pb2_grpc.pyi +38 -0
  92. chalk/_gen/chalk/server/v1/integrations_pb2.py +11 -9
  93. chalk/_gen/chalk/server/v1/integrations_pb2.pyi +34 -2
  94. chalk/_gen/chalk/server/v1/kube_pb2.py +29 -19
  95. chalk/_gen/chalk/server/v1/kube_pb2.pyi +28 -0
  96. chalk/_gen/chalk/server/v1/kube_pb2_grpc.py +45 -0
  97. chalk/_gen/chalk/server/v1/kube_pb2_grpc.pyi +12 -0
  98. chalk/_gen/chalk/server/v1/log_pb2.py +21 -3
  99. chalk/_gen/chalk/server/v1/log_pb2.pyi +68 -0
  100. chalk/_gen/chalk/server/v1/log_pb2_grpc.py +90 -0
  101. chalk/_gen/chalk/server/v1/log_pb2_grpc.pyi +24 -0
  102. chalk/_gen/chalk/server/v1/model_registry_pb2.py +10 -10
  103. chalk/_gen/chalk/server/v1/model_registry_pb2.pyi +4 -1
  104. chalk/_gen/chalk/server/v1/plandebug_pb2.py +53 -0
  105. chalk/_gen/chalk/server/v1/plandebug_pb2.pyi +86 -0
  106. chalk/_gen/chalk/server/v1/plandebug_pb2_grpc.py +168 -0
  107. chalk/_gen/chalk/server/v1/plandebug_pb2_grpc.pyi +60 -0
  108. chalk/_gen/chalk/server/v1/queries_pb2.py +66 -66
  109. chalk/_gen/chalk/server/v1/queries_pb2.pyi +32 -2
  110. chalk/_gen/chalk/server/v1/scheduled_query_run_pb2.py +12 -12
  111. chalk/_gen/chalk/server/v1/scheduled_query_run_pb2.pyi +16 -3
  112. chalk/_gen/chalk/server/v1/scheduler_pb2.py +24 -12
  113. chalk/_gen/chalk/server/v1/scheduler_pb2.pyi +61 -1
  114. chalk/_gen/chalk/server/v1/scheduler_pb2_grpc.py +90 -0
  115. chalk/_gen/chalk/server/v1/scheduler_pb2_grpc.pyi +24 -0
  116. chalk/_gen/chalk/server/v1/script_tasks_pb2.py +15 -3
  117. chalk/_gen/chalk/server/v1/script_tasks_pb2.pyi +22 -0
  118. chalk/_gen/chalk/server/v1/script_tasks_pb2_grpc.py +90 -0
  119. chalk/_gen/chalk/server/v1/script_tasks_pb2_grpc.pyi +24 -0
  120. chalk/_gen/chalk/server/v1/sql_interface_pb2.py +75 -0
  121. chalk/_gen/chalk/server/v1/sql_interface_pb2.pyi +142 -0
  122. chalk/_gen/chalk/server/v1/sql_interface_pb2_grpc.py +349 -0
  123. chalk/_gen/chalk/server/v1/sql_interface_pb2_grpc.pyi +114 -0
  124. chalk/_gen/chalk/server/v1/sql_queries_pb2.py +48 -0
  125. chalk/_gen/chalk/server/v1/sql_queries_pb2.pyi +150 -0
  126. chalk/_gen/chalk/server/v1/sql_queries_pb2_grpc.py +123 -0
  127. chalk/_gen/chalk/server/v1/sql_queries_pb2_grpc.pyi +52 -0
  128. chalk/_gen/chalk/server/v1/team_pb2.py +154 -141
  129. chalk/_gen/chalk/server/v1/team_pb2.pyi +30 -2
  130. chalk/_gen/chalk/server/v1/team_pb2_grpc.py +45 -0
  131. chalk/_gen/chalk/server/v1/team_pb2_grpc.pyi +12 -0
  132. chalk/_gen/chalk/server/v1/topic_pb2.py +5 -3
  133. chalk/_gen/chalk/server/v1/topic_pb2.pyi +10 -1
  134. chalk/_gen/chalk/server/v1/trace_pb2.py +44 -40
  135. chalk/_gen/chalk/server/v1/trace_pb2.pyi +20 -0
  136. chalk/_gen/chalk/streaming/v1/debug_service_pb2.py +62 -0
  137. chalk/_gen/chalk/streaming/v1/debug_service_pb2.pyi +75 -0
  138. chalk/_gen/chalk/streaming/v1/debug_service_pb2_grpc.py +221 -0
  139. chalk/_gen/chalk/streaming/v1/debug_service_pb2_grpc.pyi +88 -0
  140. chalk/_gen/chalk/streaming/v1/simple_streaming_service_pb2.py +16 -10
  141. chalk/_gen/chalk/streaming/v1/simple_streaming_service_pb2.pyi +52 -1
  142. chalk/_gen/chalk/streaming/v1/simple_streaming_service_pb2_grpc.py +48 -0
  143. chalk/_gen/chalk/streaming/v1/simple_streaming_service_pb2_grpc.pyi +20 -0
  144. chalk/_gen/chalk/utils/v1/field_change_pb2.py +32 -0
  145. chalk/_gen/chalk/utils/v1/field_change_pb2.pyi +42 -0
  146. chalk/_gen/chalk/utils/v1/field_change_pb2_grpc.py +4 -0
  147. chalk/_gen/chalk/utils/v1/field_change_pb2_grpc.pyi +4 -0
  148. chalk/_lsp/error_builder.py +11 -0
  149. chalk/_version.py +1 -1
  150. chalk/client/client.py +128 -43
  151. chalk/client/client_async.py +149 -0
  152. chalk/client/client_async_impl.py +22 -0
  153. chalk/client/client_grpc.py +539 -104
  154. chalk/client/client_impl.py +449 -122
  155. chalk/client/dataset.py +7 -1
  156. chalk/client/models.py +98 -0
  157. chalk/client/serialization/model_serialization.py +92 -9
  158. chalk/df/LazyFramePlaceholder.py +1154 -0
  159. chalk/features/_class_property.py +7 -0
  160. chalk/features/_embedding/embedding.py +1 -0
  161. chalk/features/_encoding/converter.py +83 -2
  162. chalk/features/feature_field.py +40 -30
  163. chalk/features/feature_set_decorator.py +1 -0
  164. chalk/features/feature_wrapper.py +42 -3
  165. chalk/features/hooks.py +81 -10
  166. chalk/features/inference.py +33 -31
  167. chalk/features/resolver.py +224 -24
  168. chalk/functions/__init__.py +65 -3
  169. chalk/gitignore/gitignore_parser.py +5 -1
  170. chalk/importer.py +142 -68
  171. chalk/ml/__init__.py +2 -0
  172. chalk/ml/model_hooks.py +194 -26
  173. chalk/ml/model_reference.py +56 -8
  174. chalk/ml/model_version.py +24 -15
  175. chalk/ml/utils.py +20 -17
  176. chalk/operators/_utils.py +10 -3
  177. chalk/parsed/_proto/export.py +22 -0
  178. chalk/parsed/duplicate_input_gql.py +3 -0
  179. chalk/parsed/json_conversions.py +20 -14
  180. chalk/parsed/to_proto.py +16 -4
  181. chalk/parsed/user_types_to_json.py +31 -10
  182. chalk/parsed/validation_from_registries.py +182 -0
  183. chalk/queries/named_query.py +16 -6
  184. chalk/queries/scheduled_query.py +9 -1
  185. chalk/serialization/parsed_annotation.py +24 -11
  186. chalk/sql/__init__.py +18 -0
  187. chalk/sql/_internal/integrations/databricks.py +55 -17
  188. chalk/sql/_internal/integrations/mssql.py +127 -62
  189. chalk/sql/_internal/integrations/redshift.py +4 -0
  190. chalk/sql/_internal/sql_file_resolver.py +53 -9
  191. chalk/sql/_internal/sql_source.py +35 -2
  192. chalk/streams/_kafka_source.py +5 -1
  193. chalk/streams/_windows.py +15 -2
  194. chalk/utils/_otel_version.py +13 -0
  195. chalk/utils/async_helpers.py +2 -2
  196. chalk/utils/missing_dependency.py +5 -4
  197. chalk/utils/tracing.py +185 -95
  198. {chalkpy-2.90.1.dist-info → chalkpy-2.95.3.dist-info}/METADATA +4 -6
  199. {chalkpy-2.90.1.dist-info → chalkpy-2.95.3.dist-info}/RECORD +202 -146
  200. {chalkpy-2.90.1.dist-info → chalkpy-2.95.3.dist-info}/WHEEL +0 -0
  201. {chalkpy-2.90.1.dist-info → chalkpy-2.95.3.dist-info}/entry_points.txt +0 -0
  202. {chalkpy-2.90.1.dist-info → chalkpy-2.95.3.dist-info}/top_level.txt +0 -0
@@ -99,10 +99,12 @@ from chalk.client.models import (
99
99
  GetRegisteredModelResponse,
100
100
  GetRegisteredModelVersionResponse,
101
101
  IngestDatasetRequest,
102
+ ManualTriggerScheduledQueryResponse,
102
103
  MultiUploadFeaturesRequest,
103
104
  MultiUploadFeaturesResponse,
104
105
  OfflineQueryContext,
105
106
  OfflineQueryInput,
107
+ OfflineQueryInputSql,
106
108
  OfflineQueryInputUri,
107
109
  OfflineQueryParquetUploadURLResponse,
108
110
  OnlineQuery,
@@ -124,6 +126,7 @@ from chalk.client.models import (
124
126
  ResolverReplayResponse,
125
127
  ResolverRunResponse,
126
128
  ResourceRequests,
129
+ ScheduledQueryRun,
127
130
  SetDatasetRevisionMetadataRequest,
128
131
  SetDatasetRevisionMetadataResponse,
129
132
  SetIncrementalProgressRequest,
@@ -173,7 +176,7 @@ from chalk.utils.log_with_context import get_logger
173
176
  from chalk.utils.missing_dependency import missing_dependency_exception
174
177
  from chalk.utils.notebook import parse_notebook_into_script
175
178
  from chalk.utils.string import s
176
- from chalk.utils.tracing import add_trace_headers
179
+ from chalk.utils.tracing import add_trace_headers, safe_trace
177
180
 
178
181
  if TYPE_CHECKING:
179
182
  import ssl
@@ -743,6 +746,8 @@ class OnlineQueryResponseImpl(OnlineQueryResult):
743
746
  self.warnings = warnings
744
747
  self.meta = meta
745
748
 
749
+ print(self.data)
750
+
746
751
  for d in self.data:
747
752
  if d.value is not None:
748
753
  try:
@@ -1872,78 +1877,82 @@ https://docs.chalk.ai/cli/apply
1872
1877
  trace: bool = False,
1873
1878
  value_metrics_tag_by_features: Sequence[FeatureReference] = (),
1874
1879
  ) -> OnlineQueryResponseImpl:
1875
- encoded_inputs, all_warnings = recursive_encode_inputs(input)
1876
- encoded_outputs = encode_outputs(output)
1877
- outputs = encoded_outputs.string_outputs
1878
- encoded_value_metrics_tag_by_features = encode_outputs(value_metrics_tag_by_features).string_outputs
1879
- if branch is ...:
1880
- branch = self._branch
1881
- now_str = None
1882
- if now is not None:
1883
- if now.tzinfo is None:
1884
- now = now.astimezone(tz=timezone.utc)
1885
- now_str = now.isoformat()
1886
-
1887
- staleness_encoded = {}
1888
- if staleness is not None:
1889
- for k, v in staleness.items():
1890
- if isinstance(k, str):
1891
- # It's a feature set
1892
- staleness_encoded[k] = v
1893
- elif is_feature_set_class(k):
1894
- staleness_encoded[k.namespace] = v
1895
- else:
1896
- staleness_encoded[ensure_feature(k).root_fqn] = v
1897
-
1898
- request = OnlineQueryRequest(
1899
- inputs=encoded_inputs,
1900
- outputs=outputs,
1901
- expression_outputs=encoded_outputs.feature_expressions_base64,
1902
- now=now_str,
1903
- staleness=staleness_encoded,
1904
- context=OnlineQueryContext(
1905
- environment=environment,
1906
- tags=tags,
1907
- required_resolver_tags=required_resolver_tags,
1908
- ),
1909
- deployment_id=preview_deployment_id,
1910
- branch_id=branch,
1911
- correlation_id=correlation_id,
1912
- query_name=query_name,
1913
- query_name_version=query_name_version,
1914
- meta=meta,
1915
- explain=explain,
1916
- include_meta=bool(include_meta or explain),
1917
- store_plan_stages=store_plan_stages,
1918
- encoding_options=encoding_options or FeatureEncodingOptions(),
1919
- planner_options=planner_options,
1920
- value_metrics_tag_by_features=tuple(encoded_value_metrics_tag_by_features),
1921
- query_context=_validate_context_dict(query_context),
1922
- overlay_graph=_get_overlay_graph_b64(),
1923
- )
1880
+ with safe_trace("query"):
1881
+ if branch is ...:
1882
+ branch = self._branch
1883
+ extra_headers = {"X-Chalk-Deployment-Type": "branch" if branch else "engine"}
1884
+ if query_name is not None:
1885
+ extra_headers["X-Chalk-Query-Name"] = query_name
1886
+ if trace:
1887
+ extra_headers = add_trace_headers(extra_headers)
1888
+ if headers:
1889
+ extra_headers.update(headers)
1890
+
1891
+ encoded_inputs, all_warnings = recursive_encode_inputs(input)
1892
+ encoded_outputs = encode_outputs(output)
1893
+ outputs = encoded_outputs.string_outputs
1894
+ encoded_value_metrics_tag_by_features = encode_outputs(value_metrics_tag_by_features).string_outputs
1895
+
1896
+ now_str = None
1897
+ if now is not None:
1898
+ if now.tzinfo is None:
1899
+ now = now.astimezone(tz=timezone.utc)
1900
+ now_str = now.isoformat()
1901
+
1902
+ staleness_encoded = {}
1903
+ if staleness is not None:
1904
+ for k, v in staleness.items():
1905
+ if isinstance(k, str):
1906
+ # It's a feature set
1907
+ staleness_encoded[k] = v
1908
+ elif is_feature_set_class(k):
1909
+ staleness_encoded[k.namespace] = v
1910
+ else:
1911
+ staleness_encoded[ensure_feature(k).root_fqn] = v
1924
1912
 
1925
- extra_headers = {"X-Chalk-Deployment-Type": "branch" if branch else "engine"}
1926
- if query_name is not None:
1927
- extra_headers["X-Chalk-Query-Name"] = query_name
1928
- if trace:
1929
- extra_headers = add_trace_headers(extra_headers)
1930
- if headers:
1931
- extra_headers.update(headers)
1913
+ request = OnlineQueryRequest(
1914
+ inputs=encoded_inputs,
1915
+ outputs=outputs,
1916
+ expression_outputs=encoded_outputs.feature_expressions_base64,
1917
+ now=now_str,
1918
+ staleness=staleness_encoded,
1919
+ context=OnlineQueryContext(
1920
+ environment=environment,
1921
+ tags=tags,
1922
+ required_resolver_tags=required_resolver_tags,
1923
+ ),
1924
+ deployment_id=preview_deployment_id,
1925
+ branch_id=branch,
1926
+ correlation_id=correlation_id,
1927
+ query_name=query_name,
1928
+ query_name_version=query_name_version,
1929
+ meta=meta,
1930
+ explain=explain,
1931
+ include_meta=bool(include_meta or explain),
1932
+ store_plan_stages=store_plan_stages,
1933
+ encoding_options=encoding_options or FeatureEncodingOptions(),
1934
+ planner_options=planner_options,
1935
+ value_metrics_tag_by_features=tuple(encoded_value_metrics_tag_by_features),
1936
+ query_context=_validate_context_dict(query_context),
1937
+ overlay_graph=_get_overlay_graph_b64(),
1938
+ )
1932
1939
 
1933
- resp = self._request(
1934
- method="POST",
1935
- uri="/v1/query/online",
1936
- json=request,
1937
- response=OnlineQueryResponse,
1938
- environment_override=environment,
1939
- preview_deployment_id=preview_deployment_id,
1940
- branch=branch,
1941
- metadata_request=False,
1942
- extra_headers=extra_headers,
1943
- timeout=request_timeout,
1944
- connect_timeout=connect_timeout,
1945
- )
1946
- return OnlineQueryResponseImpl(data=resp.data, errors=resp.errors or [], warnings=all_warnings, meta=resp.meta)
1940
+ resp = self._request(
1941
+ method="POST",
1942
+ uri="/v1/query/online",
1943
+ json=request,
1944
+ response=OnlineQueryResponse,
1945
+ environment_override=environment,
1946
+ preview_deployment_id=preview_deployment_id,
1947
+ branch=branch,
1948
+ metadata_request=False,
1949
+ extra_headers=extra_headers,
1950
+ timeout=request_timeout,
1951
+ connect_timeout=connect_timeout,
1952
+ )
1953
+ return OnlineQueryResponseImpl(
1954
+ data=resp.data, errors=resp.errors or [], warnings=all_warnings, meta=resp.meta
1955
+ )
1947
1956
 
1948
1957
  def multi_query(
1949
1958
  self,
@@ -1959,13 +1968,15 @@ https://docs.chalk.ai/cli/apply
1959
1968
  use_feather: Optional[bool] = True, # deprecated
1960
1969
  compression: Optional[str] = "uncompressed",
1961
1970
  ) -> BulkOnlineQueryResponse:
1971
+ if branch is ...:
1972
+ branch = self._branch
1962
1973
  extra_headers = {"X-Chalk-Deployment-Type": "branch" if branch else "engine"}
1963
1974
  if query_name is not None:
1964
1975
  extra_headers["X-Chalk-Query-Name"] = query_name
1976
+
1965
1977
  buffer = BytesIO()
1966
1978
  buffer.write(MULTI_QUERY_MAGIC_STR)
1967
- if branch is ...:
1968
- branch = self._branch
1979
+
1969
1980
  for query in queries:
1970
1981
  tags = query.tags
1971
1982
  encoded_inputs = {str(k): v for k, v in query.input.items()}
@@ -2068,13 +2079,13 @@ https://docs.chalk.ai/cli/apply
2068
2079
  headers: Mapping[str, str] | None = None,
2069
2080
  value_metrics_tag_by_features: Sequence[FeatureReference] = (),
2070
2081
  ) -> BulkOnlineQueryResponse:
2082
+ if branch is ...:
2083
+ branch = self._branch
2071
2084
  extra_headers = {"X-Chalk-Deployment-Type": "branch" if branch else "engine"}
2072
2085
  if query_name is not None:
2073
2086
  extra_headers["X-Chalk-Query-Name"] = query_name
2074
2087
  if headers:
2075
2088
  extra_headers.update(headers)
2076
- if branch is ...:
2077
- branch = self._branch
2078
2089
 
2079
2090
  now_str = None
2080
2091
  if now is not None:
@@ -2230,6 +2241,8 @@ https://docs.chalk.ai/cli/apply
2230
2241
  override_target_image_tag: Optional[str] = None,
2231
2242
  feature_for_lower_upper_bound: Optional[FeatureReference] = None,
2232
2243
  use_job_queue: bool = False,
2244
+ *,
2245
+ input_sql: str | None = None,
2233
2246
  ) -> DatasetImpl:
2234
2247
  run_asynchronously = (
2235
2248
  use_multiple_computers
@@ -2252,11 +2265,6 @@ https://docs.chalk.ai/cli/apply
2252
2265
  if query_name is None and query_name_version is not None:
2253
2266
  raise ValueError("Passed 'query_name_version' without 'query_name'.")
2254
2267
 
2255
- if max_samples is not None and input is not None:
2256
- raise ValueError(
2257
- "Cannot specify both 'max_samples' and 'input'. 'max_samples' is only valid when input is None."
2258
- )
2259
-
2260
2268
  if isinstance(num_shards, int) and num_shards < 1:
2261
2269
  raise ValueError("num_shards must be greater than 0")
2262
2270
  if isinstance(num_workers, int) and num_workers < 1:
@@ -2277,48 +2285,70 @@ https://docs.chalk.ai/cli/apply
2277
2285
 
2278
2286
  context = OfflineQueryContext(environment=environment)
2279
2287
 
2280
- if input is None:
2281
- query_input = None
2282
- elif isinstance(input, OfflineQueryInputUri):
2283
- query_input = input
2284
- elif isinstance(input, str):
2285
- query_input = OfflineQueryInputUri(
2286
- parquet_uri=input,
2287
- start_row=None,
2288
- end_row=None,
2289
- )
2290
- else:
2291
- # by this point, should be
2292
- # Union[QueryInput, List[QueryInput], Tuple[QueryInput, ...]]
2293
- if isinstance(input, (list, tuple)):
2294
- input_times_tuple: Sequence[QueryInputTime] = (
2295
- [None] * len(input)
2296
- if input_times is None
2297
- else [input_times for _ in input]
2298
- if isinstance(input_times, datetime)
2299
- else input_times
2288
+ _check_exclusive_options(
2289
+ {
2290
+ "input": input,
2291
+ "input_sql": input_sql,
2292
+ "max_samples": max_samples,
2293
+ }
2294
+ )
2295
+ if input_sql is not None:
2296
+ if input_times is not None:
2297
+ raise ValueError(
2298
+ f"Cannot specify `input_sql` and `input_times` together. Instead, the ChalkSQL query may output a `{TS_COL_NAME}` column"
2300
2299
  )
2301
- run_asynchronously = True
2302
- multi_input = list(zip(input, input_times_tuple))
2303
- else:
2304
- # Just a QueryInput
2305
- multi_input = [(input, cast(None, input_times))]
2300
+ if num_shards is not None:
2301
+ raise ValueError("Cannot specify `input_sql` and `num_shards` together.")
2302
+ if num_workers is not None:
2303
+ raise ValueError("Cannot specify `input_sql` and `num_workers` together.")
2306
2304
 
2307
- # defaulting to uploading input as table if inputs are large
2308
- if upload_input_as_table or _offline_query_inputs_should_be_uploaded(input) or num_shards:
2309
- with ThreadPoolExecutor(thread_name_prefix="offline_query_upload_input") as upload_input_executor:
2310
- query_input = self._upload_offline_query_input(
2311
- multi_input,
2312
- context=context,
2313
- branch=branch,
2314
- executor=upload_input_executor,
2315
- num_shards=num_shards,
2316
- )
2317
- elif run_asynchronously:
2318
- query_input = tuple(_to_offline_query_input(x, t) for x, t in multi_input)
2305
+ # Set query_input
2306
+ if input is not None:
2307
+ # Set query_input from input
2308
+ if isinstance(input, OfflineQueryInputUri):
2309
+ query_input = input
2310
+ elif isinstance(input, str):
2311
+ query_input = OfflineQueryInputUri(
2312
+ parquet_uri=input,
2313
+ start_row=None,
2314
+ end_row=None,
2315
+ )
2319
2316
  else:
2320
- assert len(multi_input) == 1, "We should default to running asynchronously if inputs is partitioned"
2321
- query_input = _to_offline_query_input(*multi_input[0])
2317
+ # by this point, should be
2318
+ # Union[QueryInput, List[QueryInput], Tuple[QueryInput, ...]]
2319
+ if isinstance(input, (list, tuple)):
2320
+ input_times_tuple: Sequence[QueryInputTime] = (
2321
+ [None] * len(input)
2322
+ if input_times is None
2323
+ else [input_times for _ in input]
2324
+ if isinstance(input_times, datetime)
2325
+ else input_times
2326
+ )
2327
+ run_asynchronously = True
2328
+ multi_input = list(zip(input, input_times_tuple))
2329
+ else:
2330
+ # Just a QueryInput
2331
+ multi_input = [(input, cast(None, input_times))]
2332
+
2333
+ # defaulting to uploading input as table if inputs are large
2334
+ if upload_input_as_table or _offline_query_inputs_should_be_uploaded(input) or num_shards:
2335
+ with ThreadPoolExecutor(thread_name_prefix="offline_query_upload_input") as upload_input_executor:
2336
+ query_input = self._upload_offline_query_input(
2337
+ multi_input,
2338
+ context=context,
2339
+ branch=branch,
2340
+ executor=upload_input_executor,
2341
+ num_shards=num_shards,
2342
+ )
2343
+ elif run_asynchronously:
2344
+ query_input = tuple(_to_offline_query_input(x, t) for x, t in multi_input)
2345
+ else:
2346
+ assert len(multi_input) == 1, "We should default to running asynchronously if inputs is partitioned"
2347
+ query_input = _to_offline_query_input(*multi_input[0])
2348
+ elif input_sql is not None:
2349
+ query_input = OfflineQueryInputSql(input_sql=input_sql)
2350
+ else:
2351
+ query_input = None
2322
2352
 
2323
2353
  response = self._create_dataset_job(
2324
2354
  optional_output=optional_output_root_fqns,
@@ -2349,9 +2379,9 @@ https://docs.chalk.ai/cli/apply
2349
2379
  override_target_image_tag=override_target_image_tag,
2350
2380
  num_shards=num_shards,
2351
2381
  num_workers=num_workers,
2352
- feature_for_lower_upper_bound=str(feature_for_lower_upper_bound)
2353
- if feature_for_lower_upper_bound is not None
2354
- else None,
2382
+ feature_for_lower_upper_bound=(
2383
+ str(feature_for_lower_upper_bound) if feature_for_lower_upper_bound is not None else None
2384
+ ),
2355
2385
  completion_deadline=completion_deadline,
2356
2386
  max_retries=max_retries,
2357
2387
  optional_output_expressions=optional_output_expressions,
@@ -2381,6 +2411,111 @@ https://docs.chalk.ai/cli/apply
2381
2411
  initialized_dataset.is_finished = True
2382
2412
  return initialized_dataset
2383
2413
 
2414
+ def run_scheduled_query(
2415
+ self,
2416
+ name: str,
2417
+ planner_options: Optional[Mapping[str, Any]] = None,
2418
+ incremental_resolvers: Optional[Sequence[str]] = None,
2419
+ max_samples: Optional[int] = None,
2420
+ env_overrides: Optional[Mapping[str, str]] = None,
2421
+ ) -> ManualTriggerScheduledQueryResponse:
2422
+ """
2423
+ Manually trigger a scheduled query request.
2424
+
2425
+ Parameters
2426
+ ----------
2427
+ name
2428
+ The name of the scheduled query to be triggered.
2429
+ incremental_resolvers
2430
+ If set to None, Chalk will incrementalize resolvers in the query's root namespaces.
2431
+ If set to a list of resolvers, this set will be used for incrementalization.
2432
+ Incremental resolvers must return a feature time in its output, and must return a `DataFrame`.
2433
+ Most commonly, this will be the name of a SQL file resolver. Chalk will ingest all new data
2434
+ from these resolvers and propagate changes to values in the root namespace.
2435
+ max_samples
2436
+ The maximum number of samples to compute.
2437
+ env_overrides:
2438
+ A dictionary of environment values to override during this specific triggered query.
2439
+
2440
+ Other Parameters
2441
+ ----------------
2442
+ planner_options
2443
+ A dictionary of options to pass to the planner.
2444
+ These are typically provided by Chalk Support for specific use cases.
2445
+
2446
+ Returns
2447
+ -------
2448
+ ManualTriggerScheduledQueryResponse
2449
+ A response message containing metadata around the triggered run.
2450
+
2451
+ Examples
2452
+ --------
2453
+ >>> from chalk.client.client_grpc import ChalkGRPCClient
2454
+ >>> ChalkGRPCClient().run_scheduled_query(
2455
+ ... name="my_scheduled_query",
2456
+ ... )
2457
+ """
2458
+ from chalk.client.client_grpc import ChalkGRPCClient
2459
+
2460
+ client_grpc = ChalkGRPCClient(
2461
+ client_id=self._client_id,
2462
+ client_secret=self._client_secret,
2463
+ environment=self._primary_environment,
2464
+ api_server=self._api_server,
2465
+ )
2466
+
2467
+ resp = client_grpc.run_scheduled_query(
2468
+ name=name,
2469
+ planner_options=planner_options,
2470
+ incremental_resolvers=incremental_resolvers,
2471
+ max_samples=max_samples,
2472
+ env_overrides=env_overrides,
2473
+ )
2474
+
2475
+ return resp
2476
+
2477
+ def get_scheduled_query_run_history(
2478
+ self,
2479
+ name: str,
2480
+ limit: int = 10,
2481
+ ) -> List[ScheduledQueryRun]:
2482
+ """
2483
+ Get the run history for a scheduled query.
2484
+
2485
+ Parameters
2486
+ ----------
2487
+ name
2488
+ The name of the scheduled query.
2489
+ limit
2490
+ The maximum number of runs to return. Defaults to 10.
2491
+
2492
+ Returns
2493
+ -------
2494
+ list[ScheduledQueryRun]
2495
+ A response message containing the list of scheduled query runs.
2496
+
2497
+ Examples
2498
+ --------
2499
+ >>> from chalk.client import ChalkClient
2500
+ >>> ChalkClient().get_scheduled_query_run_history(
2501
+ ... name="my_scheduled_query",
2502
+ ... limit=20,
2503
+ ... )
2504
+ """
2505
+ from chalk.client.client_grpc import ChalkGRPCClient
2506
+
2507
+ client_grpc = ChalkGRPCClient(
2508
+ client_id=self._client_id,
2509
+ client_secret=self._client_secret,
2510
+ environment=self._primary_environment,
2511
+ api_server=self._api_server,
2512
+ )
2513
+
2514
+ return client_grpc.get_scheduled_query_run_history(
2515
+ name=name,
2516
+ limit=limit,
2517
+ )
2518
+
2384
2519
  def prompt_evaluation(
2385
2520
  self,
2386
2521
  prompts: list[Prompt | str],
@@ -3442,6 +3577,7 @@ https://docs.chalk.ai/cli/apply
3442
3577
  Optional[OfflineQueryInput],
3443
3578
  UploadedParquetShardedOfflineQueryInput,
3444
3579
  OfflineQueryInputUri,
3580
+ OfflineQueryInputSql,
3445
3581
  ],
3446
3582
  max_samples: Optional[int],
3447
3583
  dataset_name: Optional[str],
@@ -4355,6 +4491,187 @@ https://docs.chalk.ai/cli/apply
4355
4491
  )
4356
4492
  return resp
4357
4493
 
4494
+ def _run_serialized_query(
4495
+ self,
4496
+ serialized_plan_bytes: bytes,
4497
+ input: Union[Mapping[FeatureReference, Sequence[Any]], pa.Table],
4498
+ output: Sequence[FeatureReference] = (),
4499
+ staleness: Optional[Mapping[FeatureReference, str]] = None,
4500
+ context: Optional[OnlineQueryContext] = None,
4501
+ query_name: Optional[str] = None,
4502
+ query_name_version: Optional[str] = None,
4503
+ correlation_id: Optional[str] = None,
4504
+ include_meta: bool = False,
4505
+ explain: bool = False,
4506
+ store_plan_stages: bool = False,
4507
+ meta: Optional[Mapping[str, str]] = None,
4508
+ headers: Mapping[str, str] | None = None,
4509
+ ) -> BulkOnlineQueryResult:
4510
+ """Run a query using a pre-serialized plan.
4511
+
4512
+ This is a protected method for internal use and testing.
4513
+
4514
+ Parameters
4515
+ ----------
4516
+ serialized_plan_bytes
4517
+ The serialized BatchPlan protobuf bytes
4518
+ input
4519
+ The input data, either as a mapping of features to values or as a PyArrow table
4520
+ output
4521
+ The output features to compute
4522
+ staleness
4523
+ Maximum staleness overrides for features
4524
+ context
4525
+ Query context including environment and tags
4526
+ query_name
4527
+ The name of the query
4528
+ query_name_version
4529
+ The version of the query
4530
+ correlation_id
4531
+ Correlation ID for logging
4532
+ include_meta
4533
+ Whether to include metadata in the response
4534
+ explain
4535
+ Whether to include explain output
4536
+ store_plan_stages
4537
+ Whether to store plan stages
4538
+ meta
4539
+ Customer metadata tags
4540
+ headers
4541
+ Additional headers to provide with the request
4542
+
4543
+ Returns
4544
+ -------
4545
+ OnlineQueryResult
4546
+ The query result
4547
+ """
4548
+ try:
4549
+ import pyarrow as pa
4550
+ import pyarrow.feather as feather
4551
+ except ImportError:
4552
+ raise missing_dependency_exception("chalkpy[runtime]")
4553
+
4554
+ # Convert input to PyArrow table if needed
4555
+ if isinstance(input, Mapping):
4556
+ # Convert mapping to PyArrow table
4557
+ table_dict = {}
4558
+ for feat_ref, values in input.items():
4559
+ feat_name = str(feat_ref)
4560
+ # Ensure values is a list
4561
+ if not isinstance(values, list):
4562
+ values = [values]
4563
+ table_dict[feat_name] = values
4564
+ input_table = pa.Table.from_pydict(table_dict)
4565
+ else:
4566
+ input_table = input
4567
+
4568
+ # Encode outputs
4569
+ outputs_encoded = encode_outputs(output).string_outputs if output else []
4570
+
4571
+ # Encode staleness
4572
+ staleness_encoded = {}
4573
+ if staleness is not None:
4574
+ for k, v in staleness.items():
4575
+ if is_feature_set_class(k):
4576
+ for f in k.features:
4577
+ staleness_encoded[f.root_fqn] = v
4578
+ else:
4579
+ staleness_encoded[ensure_feature(k).root_fqn] = v
4580
+
4581
+ # Create FeatherRequestHeader
4582
+ from chalk.client.models import OnlineQueryContext as OQC
4583
+
4584
+ header_dict = {
4585
+ "outputs": outputs_encoded,
4586
+ "expression_outputs": [],
4587
+ "staleness": staleness_encoded if staleness_encoded else None,
4588
+ "context": (context or OQC()).dict(),
4589
+ "include_meta": include_meta,
4590
+ "explain": explain,
4591
+ "correlation_id": correlation_id,
4592
+ "query_name": query_name,
4593
+ "query_name_version": query_name_version,
4594
+ "meta": meta,
4595
+ "store_plan_stages": store_plan_stages,
4596
+ }
4597
+ header_json = json.dumps(header_dict).encode("utf-8")
4598
+
4599
+ # Serialize the input table to feather format
4600
+ feather_buffer = BytesIO()
4601
+ feather.write_feather(input_table, feather_buffer)
4602
+ feather_bytes = feather_buffer.getvalue()
4603
+
4604
+ # Build the request body:
4605
+ # 1. First 8 bytes: int64 (big-endian) - length of serialized plan
4606
+ # 2. Next N bytes: serialized BatchPlan protobuf
4607
+ # 3. Next 8 bytes: int64 (big-endian) - length of header JSON
4608
+ # 4. Next M bytes: UTF-8 encoded JSON header (FeatherRequestHeader)
4609
+ # 5. Next 8 bytes: int64 (big-endian) - length of feather data
4610
+ # 6. Remaining bytes: feather-encoded input data
4611
+ request_body = BytesIO()
4612
+ request_body.write(len(serialized_plan_bytes).to_bytes(8, byteorder="big"))
4613
+ request_body.write(serialized_plan_bytes)
4614
+ request_body.write(len(header_json).to_bytes(8, byteorder="big"))
4615
+ request_body.write(header_json)
4616
+ request_body.write(len(feather_bytes).to_bytes(8, byteorder="big"))
4617
+ request_body.write(feather_bytes)
4618
+
4619
+ # Make the HTTP request
4620
+ response = self._request(
4621
+ method="POST",
4622
+ uri="/v1/query/run",
4623
+ response=None, # We'll handle the response manually
4624
+ json=None,
4625
+ data=request_body.getvalue(),
4626
+ environment_override=None,
4627
+ preview_deployment_id=None,
4628
+ branch=None,
4629
+ metadata_request=False,
4630
+ extra_headers=headers,
4631
+ )
4632
+
4633
+ if not isinstance(response, requests.Response): # pyright: ignore[reportUnnecessaryIsInstance]
4634
+ raise TypeError("Expected requests.Response")
4635
+
4636
+ if response.status_code != 200:
4637
+ raise RuntimeError(f"Request failed with status {response.status_code}: {response.text}")
4638
+
4639
+ # Deserialize the response
4640
+ result = OnlineQueryResultFeather.deserialize(response.content)
4641
+
4642
+ # Convert feather bytes back to a dataframe
4643
+ scalars_df = None
4644
+ if result.scalar_data:
4645
+ scalars_table = feather.read_table(BytesIO(result.scalar_data))
4646
+ scalars_df = pa_table_to_pl_df(scalars_table)
4647
+
4648
+ # Parse errors from JSON strings back to ChalkError objects
4649
+ errors = []
4650
+ if result.errors:
4651
+ for error_json in result.errors:
4652
+ try:
4653
+ error_dict = json.loads(error_json)
4654
+ errors.append(ChalkError(**error_dict))
4655
+ except Exception:
4656
+ # If parsing fails, create a generic error
4657
+ errors.append(ChalkError.create(code=ErrorCode.PARSE_FAILED, message=str(error_json)))
4658
+
4659
+ # Parse meta if present
4660
+ query_meta = None
4661
+ if result.meta:
4662
+ try:
4663
+ query_meta = QueryMeta(**json.loads(result.meta))
4664
+ except Exception:
4665
+ pass
4666
+
4667
+ # Return as BulkOnlineQueryResult
4668
+ return BulkOnlineQueryResult(
4669
+ scalars_df=scalars_df,
4670
+ groups_dfs=None,
4671
+ errors=errors if errors else None,
4672
+ meta=query_meta,
4673
+ )
4674
+
4358
4675
  def _to_value(self, x: FeatureResult):
4359
4676
  f: Feature = Feature.from_root_fqn(x.field)
4360
4677
 
@@ -4942,6 +5259,7 @@ https://docs.chalk.ai/cli/apply
4942
5259
  name: str,
4943
5260
  model_artifact_id: Optional[str] = None,
4944
5261
  run_id: Optional[str] = None,
5262
+ run_name: Optional[str] = None,
4945
5263
  criterion: Optional[ModelRunCriterion] = None,
4946
5264
  aliases: Optional[List[str]] = None,
4947
5265
  ) -> RegisterModelVersionResponse:
@@ -4958,6 +5276,7 @@ https://docs.chalk.ai/cli/apply
4958
5276
  name=name,
4959
5277
  model_artifact_id=model_artifact_id,
4960
5278
  run_id=run_id,
5279
+ run_name=run_name,
4961
5280
  criterion=criterion,
4962
5281
  aliases=aliases,
4963
5282
  )
@@ -5021,3 +5340,11 @@ https://docs.chalk.ai/cli/apply
5021
5340
  client_grpc.follow_model_training_job(operation_id=task_response.task_id)
5022
5341
 
5023
5342
  return CreateModelTrainingJobResponse(success=True)
5343
+
5344
+
5345
+ def _check_exclusive_options(options: dict[str, Any | None]):
5346
+ filled_options = {k: v for k, v in options.items() if v is not None}
5347
+ if len(filled_options) > 1:
5348
+ raise ValueError(
5349
+ f"Only one of the options: {', '.join(filled_options.keys())} can be specified (they are mutually exclusive options)."
5350
+ )