chalkruntime 3.35.7__tar.gz → 3.35.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 (113) hide show
  1. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/PKG-INFO +1 -1
  2. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/convert_chalkpy_underscore.py +63 -5
  3. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime.egg-info/PKG-INFO +1 -1
  4. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/pyproject.toml +1 -1
  5. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/README.md +0 -0
  6. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/__init__.py +0 -0
  7. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/constants.py +0 -0
  8. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/dataframe/__init__.py +0 -0
  9. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/dataframe/dataframe.py +0 -0
  10. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/dataframe/lazyframe.py +0 -0
  11. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/exc/__init__.py +0 -0
  12. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/exc/failed_argument.py +0 -0
  13. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/exc/resolver_errors.py +0 -0
  14. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/exc/wrapped_resolver_exception.py +0 -0
  15. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/__init__.py +0 -0
  16. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/chalk_overload.py +0 -0
  17. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/feature.py +0 -0
  18. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/filter_conversion.py +0 -0
  19. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/global_graph.py +0 -0
  20. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/graph.py +0 -0
  21. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/graph_impl.py +0 -0
  22. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/graph_proxy.py +0 -0
  23. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/graph_state.py +0 -0
  24. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/jinja_parser.py +0 -0
  25. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/materializations.py +0 -0
  26. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/maybe_named_collection.py +0 -0
  27. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/named_query.py +0 -0
  28. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/nearest_neighbor.py +0 -0
  29. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/overlay_graph.py +0 -0
  30. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/prompt_service.py +0 -0
  31. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/protograph_deserializer.py +0 -0
  32. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/protograph_serializer.py +0 -0
  33. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/resolver.py +0 -0
  34. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/singletons.py +0 -0
  35. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/sklearn_model_parser.py +0 -0
  36. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/stream_resolver.py +0 -0
  37. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/underscore.py +0 -0
  38. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/underscore_codec_info.py +0 -0
  39. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/underscore_operation_registry.py +0 -0
  40. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/graph/variables.py +0 -0
  41. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/heaptrack_launcher.py +0 -0
  42. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/incrementalization/__init__.py +0 -0
  43. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/incrementalization/group_incrementalizer.py +0 -0
  44. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/incrementalization/incrementalizer.py +0 -0
  45. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/__init__.py +0 -0
  46. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/batch_result_collector.py +0 -0
  47. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/bound_invoker.py +0 -0
  48. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/bound_invoker_cache.py +0 -0
  49. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/general_bound_invoker.py +0 -0
  50. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/no_arg_scalar_invoker.py +0 -0
  51. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/one_to_one_invoker.py +0 -0
  52. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/overlay_features.py +0 -0
  53. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/parse_external_resolver.py +0 -0
  54. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/partition_batch.py +0 -0
  55. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/query_execution_parameters.py +0 -0
  56. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/resolver_args_builder.py +0 -0
  57. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/resolver_input.py +0 -0
  58. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/resolver_input_upload.py +0 -0
  59. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/resolver_output_metadata.py +0 -0
  60. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/resolver_raw_output_parsing.py +0 -0
  61. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/resolver_result.py +0 -0
  62. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/resolver_runner.py +0 -0
  63. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/sample.py +0 -0
  64. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/validator.py +0 -0
  65. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/invoker/vectorized_hasmany_sampler.py +0 -0
  66. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/loader/__init__.py +0 -0
  67. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/loader/converter.py +0 -0
  68. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/loader/importer.py +0 -0
  69. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/memray_launcher.py +0 -0
  70. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/metadata.py +0 -0
  71. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/py.typed +0 -0
  72. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/server/__init__.py +0 -0
  73. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/server/branch_model_endpoint_config.py +0 -0
  74. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/server/config.py +0 -0
  75. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/server/entrypoint.py +0 -0
  76. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/server/env_helper.py +0 -0
  77. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/server/remote_python_function_registry_client.py +0 -0
  78. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/server/service.py +0 -0
  79. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/sql_rewriter/__init__.py +0 -0
  80. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/sql_rewriter/composed_rewriter.py +0 -0
  81. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/sql_rewriter/contextual_query_rewriter.py +0 -0
  82. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/sql_rewriter/filter_query_rewriter.py +0 -0
  83. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/sql_rewriter/identity_rewriter.py +0 -0
  84. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/sql_rewriter/query_rewriter.py +0 -0
  85. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/sql_rewriter/query_rewriter_helper.py +0 -0
  86. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/__init__.py +0 -0
  87. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/converter_utils.py +0 -0
  88. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/exc.py +0 -0
  89. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/message_parsing.py +0 -0
  90. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/resolver_utils.py +0 -0
  91. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/streaming_invoker_kernel/__init__.py +0 -0
  92. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/streaming_invoker_kernel/local_streaming_invoker_kernel.py +0 -0
  93. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/types.py +0 -0
  94. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/streaming/window_keys.py +0 -0
  95. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/utils/__init__.py +0 -0
  96. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/utils/async_helpers.py +0 -0
  97. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/utils/contextvars.py +0 -0
  98. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/utils/datadog.py +0 -0
  99. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/utils/internal_pl_utils.py +0 -0
  100. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/utils/posix_file_lock.py +0 -0
  101. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/utils/tracing.py +0 -0
  102. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/utils/viztracer_profiling.py +0 -0
  103. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime/valgrind_launcher.py +0 -0
  104. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime.egg-info/SOURCES.txt +0 -0
  105. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime.egg-info/dependency_links.txt +0 -0
  106. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime.egg-info/requires.txt +0 -0
  107. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/chalkruntime.egg-info/top_level.txt +0 -0
  108. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/setup.cfg +0 -0
  109. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/setup.py +0 -0
  110. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/tests/test_branch_model_endpoint_config.py +0 -0
  111. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/tests/test_captured_global_function_refs.py +0 -0
  112. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/tests/test_graph_cache.py +0 -0
  113. {chalkruntime-3.35.7 → chalkruntime-3.35.8}/tests/test_posix_file_lock.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalkruntime
3
- Version: 3.35.7
3
+ Version: 3.35.8
4
4
  Summary: Runtime support library for Chalk AI
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -43,6 +43,7 @@ from chalkruntime.graph.feature import (
43
43
  GroupByFeatureType,
44
44
  HasManyFeatureType,
45
45
  HasOneFeatureType,
46
+ HasOnePathObjParsed,
46
47
  NestedFeatureType,
47
48
  OutputUnderscoreFeatureType,
48
49
  ScalarFeatureType,
@@ -2661,23 +2662,80 @@ def _convert_underscore_materialized_aggregation(
2661
2662
  _aggregate_key = aggregate_operand.feature_keys[0]
2662
2663
 
2663
2664
  aggregate_hasmany_parsed = aggregate_operand.parent
2664
- if len(aggregate_hasmany_parsed.path) != 1:
2665
+ # Accept either a direct has-many (path length 1) or a single has-one followed by a has-many
2666
+ # (path length 2). The latter supports expressions like `_.user.transactions.count()` on a
2667
+ # parent feature class that reaches the events through a has-one. Multi-hop chains aren't
2668
+ # supported because the chalkpy parser only validates a single has-one prefix; keep the engine
2669
+ # in lockstep.
2670
+ path_len = len(aggregate_hasmany_parsed.path)
2671
+ intermediate: HasOneFeatureType | None = None
2672
+ if path_len == 1:
2673
+ aggregate_hasmany: HasOneFeatureType | HasManyFeatureType = aggregate_hasmany_parsed.path[0]
2674
+ elif path_len == 2:
2675
+ prefix = aggregate_hasmany_parsed.path[0]
2676
+ if not isinstance(prefix, HasOneFeatureType):
2677
+ raise ValueError(
2678
+ f"The windowed aggregation operation '{window_materialization.aggregation}' only supports "
2679
+ + f"a single has-one prefix before the has-many; got '{prefix}' in path"
2680
+ )
2681
+ intermediate = prefix
2682
+ aggregate_hasmany = aggregate_hasmany_parsed.path[1]
2683
+ else:
2665
2684
  raise ValueError(
2666
- f"The windowed aggregation operation '{window_materialization.aggregation}' can only be applied to a has-many, not a nested relationship"
2685
+ f"The windowed aggregation operation '{window_materialization.aggregation}' can only be applied to "
2686
+ + "a has-many directly or via a single has-one prefix, not a longer nested relationship"
2667
2687
  )
2668
2688
 
2669
- aggregate_hasmany: HasOneFeatureType | HasManyFeatureType = aggregate_hasmany_parsed.path[0]
2670
-
2671
2689
  if isinstance(aggregate_hasmany, HasOneFeatureType):
2672
2690
  raise ValueError(
2673
2691
  f"The windowed aggregation operation '{window_materialization.aggregation}' can only be applied to a has-many, not to a has-one relationship '{aggregate_hasmany}'"
2674
2692
  )
2675
2693
 
2694
+ # group_by_keys are the inputs to the synthetic underscore resolver that fetches
2695
+ # the materialized value for `for_feature`. The resolver's output is on
2696
+ # `for_feature.root_namespace`, so its inputs must live there too — otherwise the
2697
+ # planner refuses to run it with "input and output namespaces must match".
2698
+ #
2699
+ # Direct has-many (`_.transactions.count()` on User): the has-many's local join
2700
+ # features are already on `User` (== for_feature.root_namespace), so use them.
2701
+ #
2702
+ # has-one prefix (`_.user.transactions.count()` on FraudFeatures): the has-many's
2703
+ # local join features (e.g. User.id) live on the intermediate namespace, not on
2704
+ # `for_feature.root_namespace`. Wrap each one in a NestedFeatureType through the
2705
+ # has-one (`FraudFeatures.user.id`) so its root_namespace becomes the parent's; the
2706
+ # engine resolver walks the has-one at lookup time, so we don't have to assume the
2707
+ # parent FK and the intermediate PK are name-equivalent. The materialization tiles
2708
+ # themselves remain keyed by `Transaction.user_id` via `window_materialization
2709
+ # .group_by`; only the resolver's input namespace shifts.
2710
+ if intermediate is not None:
2711
+ # Defense in depth: chalkpy validates that the has-one's foreign keys overlap
2712
+ # with the has-many's local keys at parse time; mirror that check here so the
2713
+ # engine doesn't depend on frontend validation alone.
2714
+ intermediate_foreign_keys = {f.fqn for f in intermediate.get_foreign_join_features()}
2715
+ has_many_local_keys = {f.fqn for f in aggregate_hasmany.get_local_join_features()}
2716
+ if not intermediate_foreign_keys.issubset(has_many_local_keys):
2717
+ raise ValueError(
2718
+ "Join keys do not match for has-one prefix on materialized aggregation "
2719
+ + f"'{for_feature.fqn}': has-one '{intermediate.fqn}' joins via "
2720
+ + f"{sorted(intermediate_foreign_keys)} but has-many '{aggregate_hasmany.fqn}' "
2721
+ + f"joins via {sorted(has_many_local_keys)}; these must overlap."
2722
+ )
2723
+ group_by_keys = tuple(
2724
+ NestedFeatureType(
2725
+ underlying_ref=local_feat,
2726
+ path=(HasOnePathObjParsed(intermediate, local_feat),),
2727
+ _graph=intermediate.graph,
2728
+ )
2729
+ for local_feat in aggregate_hasmany.get_local_join_features()
2730
+ )
2731
+ else:
2732
+ group_by_keys = (*aggregate_hasmany.get_local_join_features(),)
2733
+
2676
2734
  return UnderscoreMaterializedAggregation(
2677
2735
  unmaterialized_underscore=resolved_underscore,
2678
2736
  original_underscore=underscore,
2679
2737
  materialization=window_materialization,
2680
- group_by_keys=(*aggregate_hasmany.get_local_join_features(),),
2738
+ group_by_keys=group_by_keys,
2681
2739
  window_duration=window_duration,
2682
2740
  source_aggregation_namespace=for_feature.root_namespace,
2683
2741
  has_many=aggregate_hasmany,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalkruntime
3
- Version: 3.35.7
3
+ Version: 3.35.8
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.35.7"
45
+ version = "3.35.8"
46
46
 
47
47
 
48
48
  [tool.deptry]
File without changes
File without changes
File without changes