churnkit 0.76.0a2__tar.gz → 0.76.1a1__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 (326) hide show
  1. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/PKG-INFO +1 -1
  2. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/01_data_discovery.ipynb +5 -3
  3. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/pyproject.toml +1 -1
  4. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/.claude/settings.local.json +2 -1
  5. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/__init__.py +1 -1
  6. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/notebook_progress.py +10 -1
  7. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/config/experiments.py +60 -0
  8. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/databricks_init.py +46 -3
  9. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/.gitignore +0 -0
  10. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/LICENSE +0 -0
  11. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/README.md +0 -0
  12. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/constraints/.gitkeep +0 -0
  13. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/00_start_here.ipynb +0 -0
  14. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/01a_a_temporal_text_deep_dive.ipynb +0 -0
  15. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/01a_temporal_deep_dive.ipynb +0 -0
  16. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/01b_temporal_quality.ipynb +0 -0
  17. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/01c_temporal_patterns.ipynb +0 -0
  18. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/01d_event_aggregation.ipynb +0 -0
  19. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/02_column_deep_dive.ipynb +0 -0
  20. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/02a_text_columns_deep_dive.ipynb +0 -0
  21. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/03_quality_assessment.ipynb +0 -0
  22. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/04_relationship_analysis.ipynb +0 -0
  23. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/05_multi_dataset.ipynb +0 -0
  24. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/06_feature_opportunities.ipynb +0 -0
  25. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/07_modeling_readiness.ipynb +0 -0
  26. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/08_baseline_experiments.ipynb +0 -0
  27. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/09_business_alignment.ipynb +0 -0
  28. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/10_spec_generation.ipynb +0 -0
  29. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/11_scoring_validation.ipynb +0 -0
  30. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/exploration_notebooks/12_view_documentation.ipynb +0 -0
  31. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/README.md +0 -0
  32. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/data/create_snapshot.py +0 -0
  33. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/data/generate_retail_dataset.py +0 -0
  34. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/data/generate_test_data.py +0 -0
  35. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/data/migrate_parquet_to_delta.py +0 -0
  36. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/data/migrate_to_temporal.py +0 -0
  37. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/databricks/build_wheel.sh +0 -0
  38. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/databricks/capture_runtime.py +0 -0
  39. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/databricks/dbr_init.sh +0 -0
  40. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/databricks/generate_constraints.py +0 -0
  41. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/databricks/notebook_setup.py +0 -0
  42. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/notebooks/clean_notebook_outputs.py +0 -0
  43. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/notebooks/export_tutorial_html.py +0 -0
  44. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/notebooks/init_project.py +0 -0
  45. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/notebooks/plotly_image_preprocessor.py +0 -0
  46. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/notebooks/run_exploration.py +0 -0
  47. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/notebooks/test_notebooks.py +0 -0
  48. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/release.sh +0 -0
  49. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/templates/tutorial_html/conf.json +0 -0
  50. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/templates/tutorial_html/index.html.j2 +0 -0
  51. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/scripts/update_notebook_paths.py +0 -0
  52. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/__init__.py +0 -0
  53. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/auto_explorer/__init__.py +0 -0
  54. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/auto_explorer/exploration_manager.py +0 -0
  55. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/auto_explorer/explorer.py +0 -0
  56. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/auto_explorer/findings.py +0 -0
  57. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/auto_explorer/layered_recommendations.py +0 -0
  58. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/auto_explorer/recommendation_builder.py +0 -0
  59. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/auto_explorer/recommendations.py +0 -0
  60. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/business/__init__.py +0 -0
  61. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/business/ab_test_designer.py +0 -0
  62. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/business/fairness_analyzer.py +0 -0
  63. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/business/intervention_matcher.py +0 -0
  64. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/business/report_generator.py +0 -0
  65. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/business/risk_profile.py +0 -0
  66. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/business/roi_analyzer.py +0 -0
  67. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/diagnostics/__init__.py +0 -0
  68. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/diagnostics/calibration_analyzer.py +0 -0
  69. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/diagnostics/cv_analyzer.py +0 -0
  70. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/diagnostics/error_analyzer.py +0 -0
  71. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/diagnostics/leakage_detector.py +0 -0
  72. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/diagnostics/noise_tester.py +0 -0
  73. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/diagnostics/overfitting_analyzer.py +0 -0
  74. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/diagnostics/segment_analyzer.py +0 -0
  75. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/discovery/__init__.py +0 -0
  76. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/discovery/config_generator.py +0 -0
  77. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/discovery/discovery_flow.py +0 -0
  78. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/discovery/type_inferencer.py +0 -0
  79. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/interpretability/__init__.py +0 -0
  80. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/interpretability/cohort_analyzer.py +0 -0
  81. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/interpretability/counterfactual.py +0 -0
  82. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/interpretability/individual_explainer.py +0 -0
  83. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/interpretability/pdp_generator.py +0 -0
  84. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/interpretability/shap_explainer.py +0 -0
  85. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/jupyter_save_hook.py +0 -0
  86. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/notebook_html_exporter.py +0 -0
  87. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/plotly_preprocessor.py +0 -0
  88. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/__init__.py +0 -0
  89. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/base.py +0 -0
  90. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/cleaning/__init__.py +0 -0
  91. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/cleaning/consistency.py +0 -0
  92. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/cleaning/deduplicate.py +0 -0
  93. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/cleaning/impute.py +0 -0
  94. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/cleaning/outlier.py +0 -0
  95. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/datetime/__init__.py +0 -0
  96. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/datetime/extract.py +0 -0
  97. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/encoding/__init__.py +0 -0
  98. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/encoding/categorical.py +0 -0
  99. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/pipeline.py +0 -0
  100. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/registry.py +0 -0
  101. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/selection/__init__.py +0 -0
  102. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/selection/drop_column.py +0 -0
  103. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/transform/__init__.py +0 -0
  104. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/transform/power.py +0 -0
  105. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/recommendations/transform/scale.py +0 -0
  106. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/visualization/__init__.py +0 -0
  107. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/visualization/chart_builder.py +0 -0
  108. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/visualization/console.py +0 -0
  109. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/visualization/display.py +0 -0
  110. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/analysis/visualization/number_formatter.py +0 -0
  111. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/artifacts/__init__.py +0 -0
  112. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/artifacts/fit_artifact_registry.py +0 -0
  113. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/cli.py +0 -0
  114. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/__init__.py +0 -0
  115. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/compat/__init__.py +0 -0
  116. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/compat/detection.py +0 -0
  117. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/compat/ops.py +0 -0
  118. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/compat/pandas_backend.py +0 -0
  119. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/compat/spark_backend.py +0 -0
  120. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/__init__.py +0 -0
  121. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/base.py +0 -0
  122. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/__init__.py +0 -0
  123. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/deployer.py +0 -0
  124. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/explainer.py +0 -0
  125. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/feature_eng.py +0 -0
  126. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/ingester.py +0 -0
  127. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/profiler.py +0 -0
  128. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/trainer.py +0 -0
  129. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/transformer.py +0 -0
  130. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/components/validator.py +0 -0
  131. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/enums.py +0 -0
  132. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/orchestrator.py +0 -0
  133. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/components/registry.py +0 -0
  134. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/config/__init__.py +0 -0
  135. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/config/column_config.py +0 -0
  136. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/config/pipeline_config.py +0 -0
  137. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/config/source_config.py +0 -0
  138. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/utils/__init__.py +0 -0
  139. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/utils/leakage.py +0 -0
  140. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/utils/severity.py +0 -0
  141. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/core/utils/statistics.py +0 -0
  142. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/__init__.py +0 -0
  143. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/__init__.py +0 -0
  144. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/base.py +0 -0
  145. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/cell_builder.py +0 -0
  146. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/config.py +0 -0
  147. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/databricks_generator.py +0 -0
  148. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/local_generator.py +0 -0
  149. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/project_init.py +0 -0
  150. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/runner.py +0 -0
  151. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/script_generator.py +0 -0
  152. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/__init__.py +0 -0
  153. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/base_stage.py +0 -0
  154. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s01_ingestion.py +0 -0
  155. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s02_profiling.py +0 -0
  156. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s03_cleaning.py +0 -0
  157. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s04_transformation.py +0 -0
  158. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s05_feature_engineering.py +0 -0
  159. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s06_feature_selection.py +0 -0
  160. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s07_model_training.py +0 -0
  161. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s08_deployment.py +0 -0
  162. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s09_monitoring.py +0 -0
  163. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s10_batch_inference.py +0 -0
  164. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/notebook_generator/stages/s11_feature_store.py +0 -0
  165. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/orchestration/__init__.py +0 -0
  166. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/orchestration/code_generator.py +0 -0
  167. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/orchestration/context.py +0 -0
  168. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/orchestration/data_materializer.py +0 -0
  169. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/orchestration/databricks_exporter.py +0 -0
  170. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/orchestration/doc_generator.py +0 -0
  171. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/pipeline_generator/__init__.py +0 -0
  172. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/pipeline_generator/findings_parser.py +0 -0
  173. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/pipeline_generator/generator.py +0 -0
  174. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/pipeline_generator/models.py +0 -0
  175. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/pipeline_generator/renderer.py +0 -0
  176. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/spec_generator/__init__.py +0 -0
  177. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/spec_generator/databricks_generator.py +0 -0
  178. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/spec_generator/generic_generator.py +0 -0
  179. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/spec_generator/mlflow_pipeline_generator.py +0 -0
  180. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/generators/spec_generator/pipeline_spec.py +0 -0
  181. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/__init__.py +0 -0
  182. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/__init__.py +0 -0
  183. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/base.py +0 -0
  184. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/factory.py +0 -0
  185. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/feature_store/__init__.py +0 -0
  186. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/feature_store/base.py +0 -0
  187. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/feature_store/databricks.py +0 -0
  188. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/feature_store/feast_adapter.py +0 -0
  189. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/feature_store/local.py +0 -0
  190. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/mlflow/__init__.py +0 -0
  191. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/mlflow/base.py +0 -0
  192. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/mlflow/databricks.py +0 -0
  193. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/mlflow/experiment_tracker.py +0 -0
  194. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/mlflow/local.py +0 -0
  195. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/storage/__init__.py +0 -0
  196. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/storage/base.py +0 -0
  197. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/storage/databricks.py +0 -0
  198. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/adapters/storage/local.py +0 -0
  199. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/feature_store/__init__.py +0 -0
  200. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/feature_store/definitions.py +0 -0
  201. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/feature_store/manager.py +0 -0
  202. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/feature_store/registry.py +0 -0
  203. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/iteration/__init__.py +0 -0
  204. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/iteration/context.py +0 -0
  205. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/iteration/feedback_collector.py +0 -0
  206. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/iteration/orchestrator.py +0 -0
  207. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/iteration/recommendation_tracker.py +0 -0
  208. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/iteration/signals.py +0 -0
  209. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/llm_context/__init__.py +0 -0
  210. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/llm_context/context_builder.py +0 -0
  211. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/llm_context/prompts.py +0 -0
  212. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/streaming/__init__.py +0 -0
  213. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/streaming/batch_integration.py +0 -0
  214. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/streaming/early_warning_model.py +0 -0
  215. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/streaming/event_schema.py +0 -0
  216. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/streaming/online_store_writer.py +0 -0
  217. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/streaming/realtime_scorer.py +0 -0
  218. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/streaming/trigger_engine.py +0 -0
  219. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/integrations/streaming/window_aggregator.py +0 -0
  220. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/__init__.py +0 -0
  221. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/cleaning/__init__.py +0 -0
  222. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/cleaning/base.py +0 -0
  223. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/cleaning/missing_handler.py +0 -0
  224. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/cleaning/outlier_handler.py +0 -0
  225. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/deployment/__init__.py +0 -0
  226. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/deployment/batch_scorer.py +0 -0
  227. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/deployment/champion_challenger.py +0 -0
  228. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/deployment/model_registry.py +0 -0
  229. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/deployment/retraining_trigger.py +0 -0
  230. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/__init__.py +0 -0
  231. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/behavioral_features.py +0 -0
  232. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/customer_segmentation.py +0 -0
  233. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/feature_definitions.py +0 -0
  234. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/feature_engineer.py +0 -0
  235. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/feature_manifest.py +0 -0
  236. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/feature_selector.py +0 -0
  237. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/interaction_features.py +0 -0
  238. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/features/temporal_features.py +0 -0
  239. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/ingestion/__init__.py +0 -0
  240. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/ingestion/load_result.py +0 -0
  241. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/ingestion/loaders.py +0 -0
  242. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/ingestion/source_registry.py +0 -0
  243. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/__init__.py +0 -0
  244. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/baseline_trainer.py +0 -0
  245. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/cross_validator.py +0 -0
  246. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/data_splitter.py +0 -0
  247. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/feature_scaler.py +0 -0
  248. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/hyperparameter_tuner.py +0 -0
  249. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/imbalance_handler.py +0 -0
  250. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/mlflow_logger.py +0 -0
  251. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/model_comparator.py +0 -0
  252. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/model_evaluator.py +0 -0
  253. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/modeling/threshold_optimizer.py +0 -0
  254. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/monitoring/__init__.py +0 -0
  255. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/monitoring/alert_manager.py +0 -0
  256. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/monitoring/drift_detector.py +0 -0
  257. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/monitoring/performance_monitor.py +0 -0
  258. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/preprocessing/__init__.py +0 -0
  259. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/preprocessing/transformer_manager.py +0 -0
  260. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/__init__.py +0 -0
  261. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/categorical_distribution.py +0 -0
  262. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/categorical_target_analyzer.py +0 -0
  263. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/column_profiler.py +0 -0
  264. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/distribution_analysis.py +0 -0
  265. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/drift_detector.py +0 -0
  266. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/feature_capacity.py +0 -0
  267. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/pattern_analysis_config.py +0 -0
  268. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/profile_result.py +0 -0
  269. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/quality_checks.py +0 -0
  270. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/relationship_detector.py +0 -0
  271. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/relationship_recommender.py +0 -0
  272. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/report_generator.py +0 -0
  273. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/scd_analyzer.py +0 -0
  274. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/segment_analyzer.py +0 -0
  275. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/segment_aware_outlier.py +0 -0
  276. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/target_level_analyzer.py +0 -0
  277. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/temporal_analyzer.py +0 -0
  278. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/temporal_coverage.py +0 -0
  279. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/temporal_feature_analyzer.py +0 -0
  280. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/temporal_feature_engineer.py +0 -0
  281. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/temporal_pattern_analyzer.py +0 -0
  282. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/temporal_quality_checks.py +0 -0
  283. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/temporal_target_analyzer.py +0 -0
  284. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/text_embedder.py +0 -0
  285. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/text_processor.py +0 -0
  286. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/text_reducer.py +0 -0
  287. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/time_series_profiler.py +0 -0
  288. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/time_window_aggregator.py +0 -0
  289. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/type_detector.py +0 -0
  290. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/profiling/window_recommendation.py +0 -0
  291. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/__init__.py +0 -0
  292. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/access_guard.py +0 -0
  293. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/cutoff_analyzer.py +0 -0
  294. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/data_preparer.py +0 -0
  295. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/point_in_time_join.py +0 -0
  296. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/point_in_time_registry.py +0 -0
  297. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/scenario_detector.py +0 -0
  298. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/snapshot_manager.py +0 -0
  299. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/synthetic_coordinator.py +0 -0
  300. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/timestamp_discovery.py +0 -0
  301. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/temporal/timestamp_manager.py +0 -0
  302. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/transformation/__init__.py +0 -0
  303. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/transformation/binary_handler.py +0 -0
  304. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/transformation/categorical_encoder.py +0 -0
  305. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/transformation/datetime_transformer.py +0 -0
  306. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/transformation/numeric_transformer.py +0 -0
  307. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/transformation/pipeline.py +0 -0
  308. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/__init__.py +0 -0
  309. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/adversarial_scoring_validator.py +0 -0
  310. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/business_sense_gate.py +0 -0
  311. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/data_quality_gate.py +0 -0
  312. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/data_validators.py +0 -0
  313. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/feature_quality_gate.py +0 -0
  314. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/gates.py +0 -0
  315. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/leakage_gate.py +0 -0
  316. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/model_validity_gate.py +0 -0
  317. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/pipeline_validation_runner.py +0 -0
  318. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/quality_scorer.py +0 -0
  319. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/rule_generator.py +0 -0
  320. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/scoring_pipeline_validator.py +0 -0
  321. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/stages/validation/timeseries_detector.py +0 -0
  322. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/transforms/__init__.py +0 -0
  323. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/transforms/artifact_store.py +0 -0
  324. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/transforms/executor.py +0 -0
  325. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/transforms/fitted.py +0 -0
  326. {churnkit-0.76.0a2 → churnkit-0.76.1a1}/src/customer_retention/transforms/ops.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: churnkit
3
- Version: 0.76.0a2
3
+ Version: 0.76.1a1
4
4
  Summary: Structured ML framework for customer churn prediction -- from exploration notebooks to production pipelines, locally or on Databricks.
5
5
  Project-URL: Homepage, https://github.com/aladjov/CR
6
6
  Project-URL: Documentation, https://github.com/aladjov/CR/wiki
@@ -137,10 +137,12 @@
137
137
  "# =============================================================================\n",
138
138
  "\n",
139
139
  "# DATA_PATH: Path to your data file (CSV, Parquet, or Delta)\n",
140
- "DATA_PATH = \"../tests/fixtures/customer_retention_retail.csv\"\n",
140
+ "DATA_PATH = \"../tests/fixtures/customer_emails.csv\"\n",
141
+ "# or databricks /Volumes/churnkit/landing/datasets/customer_emails.csv\n",
142
+ "\n",
141
143
  "\n",
142
144
  "# TARGET_COLUMN: Your prediction target (set to None for auto-detection)\n",
143
- "TARGET_COLUMN = \"unsubscribed\"\n",
145
+ "TARGET_COLUMN = None\n",
144
146
  "\n",
145
147
  "# ENTITY_COLUMN: Customer/user ID column (set to None for auto-detection)\n",
146
148
  "ENTITY_COLUMN = None\n",
@@ -169,7 +171,7 @@
169
171
  "#\n",
170
172
  "# EVENT-LEVEL (multiple rows per customer):\n",
171
173
  "# DATA_PATH = \"../tests/fixtures/customer_transactions.csv\"\n",
172
- "DATA_PATH = \"../tests/fixtures/customer_emails.csv\"\n",
174
+ "# DATA_PATH = \"../tests/fixtures/customer_emails.csv\"\n",
173
175
  "# =============================================================================\n",
174
176
  "\n",
175
177
  "# OUTPUT_DIR: All outputs go here (gitignored)\n",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "churnkit"
3
- version = "0.76.0a2"
3
+ version = "0.76.1a1"
4
4
  description = "Structured ML framework for customer churn prediction -- from exploration notebooks to production pipelines, locally or on Databricks."
5
5
  readme = "README.md"
6
6
  license = {text = "Apache-2.0"}
@@ -3,7 +3,8 @@
3
3
  "allow": [
4
4
  "Bash(python -m pytest:*)",
5
5
  "Bash(python -m ruff check:*)",
6
- "Bash(ruff check:*)"
6
+ "Bash(ruff check:*)",
7
+ "Bash(grep:*)"
7
8
  ]
8
9
  }
9
10
  }
@@ -17,7 +17,7 @@ Main module categories:
17
17
  llm_context, iteration)
18
18
  """
19
19
 
20
- __version__ = "0.76.0a2"
20
+ __version__ = "0.76.1a1"
21
21
 
22
22
  # Environment utilities (always available)
23
23
  from .core.compat import (
@@ -5,7 +5,16 @@ from pathlib import Path
5
5
  from typing import Optional
6
6
 
7
7
  from customer_retention.core.compat import is_databricks
8
- from customer_retention.core.config.experiments import get_notebook_experiments_dir
8
+ from customer_retention.core.config.experiments import get_notebook_experiments_dir, reload_config
9
+
10
+
11
+ def _ensure_databricks_config_loaded() -> None:
12
+ if not is_databricks():
13
+ return
14
+ reload_config()
15
+
16
+
17
+ _ensure_databricks_config_loaded()
9
18
 
10
19
 
11
20
  def track_and_export_previous(current_notebook: str) -> None:
@@ -1,7 +1,49 @@
1
+ import json
1
2
  import os
2
3
  from pathlib import Path
3
4
  from typing import Optional
4
5
 
6
+ _DATABRICKS_CONFIG_FILENAME = ".churnkit_config.json"
7
+
8
+
9
+ def _workspace_config_path(workspace_path: str) -> Path:
10
+ return Path(f"/Workspace/{workspace_path}") / _DATABRICKS_CONFIG_FILENAME
11
+
12
+
13
+ def _read_config_file(path: Path) -> dict | None:
14
+ try:
15
+ return json.loads(path.read_text()) if path.exists() else None
16
+ except (json.JSONDecodeError, OSError):
17
+ return None
18
+
19
+
20
+ def _load_persisted_databricks_config() -> dict | None:
21
+ if not os.environ.get("DATABRICKS_RUNTIME_VERSION"):
22
+ return None
23
+ workspace_path = os.environ.get("CR_WORKSPACE_PATH")
24
+ if workspace_path:
25
+ return _read_config_file(_workspace_config_path(workspace_path))
26
+ cwd = Path.cwd()
27
+ for _ in range(5):
28
+ result = _read_config_file(cwd / _DATABRICKS_CONFIG_FILENAME)
29
+ if result:
30
+ return result
31
+ if cwd.parent == cwd:
32
+ break
33
+ cwd = cwd.parent
34
+ return None
35
+
36
+
37
+ def persist_databricks_config(experiments_dir: str, catalog: str, schema: str, workspace_path: str | None = None) -> None:
38
+ if not workspace_path:
39
+ return
40
+ try:
41
+ _workspace_config_path(workspace_path).write_text(json.dumps({
42
+ "experiments_dir": experiments_dir, "catalog": catalog, "schema": schema,
43
+ }))
44
+ except OSError:
45
+ pass
46
+
5
47
 
6
48
  def _find_project_root() -> Path:
7
49
  path = Path(__file__).parent
@@ -17,6 +59,9 @@ def get_experiments_dir(default: Optional[str] = None) -> Path:
17
59
  return Path(os.environ["CR_EXPERIMENTS_DIR"])
18
60
  if default:
19
61
  return Path(default)
62
+ persisted = _load_persisted_databricks_config()
63
+ if persisted and "experiments_dir" in persisted:
64
+ return Path(persisted["experiments_dir"])
20
65
  return _find_project_root() / "experiments"
21
66
 
22
67
 
@@ -64,6 +109,21 @@ WORKSPACE_PATH = get_workspace_path()
64
109
  EXPERIMENT_NAME = get_experiment_name()
65
110
 
66
111
 
112
+ def reload_config() -> None:
113
+ global EXPERIMENTS_DIR, FINDINGS_DIR, DATA_DIR, MLRUNS_DIR, FEATURE_STORE_DIR
114
+ global OUTPUT_DIR, CATALOG, SCHEMA, WORKSPACE_PATH, EXPERIMENT_NAME
115
+ EXPERIMENTS_DIR = get_experiments_dir()
116
+ FINDINGS_DIR = get_findings_dir()
117
+ DATA_DIR = get_data_dir()
118
+ MLRUNS_DIR = get_mlruns_dir()
119
+ FEATURE_STORE_DIR = get_feature_store_dir()
120
+ OUTPUT_DIR = FINDINGS_DIR
121
+ CATALOG = get_catalog()
122
+ SCHEMA = get_schema()
123
+ WORKSPACE_PATH = get_workspace_path()
124
+ EXPERIMENT_NAME = get_experiment_name()
125
+
126
+
67
127
  def setup_experiments_structure(experiments_dir: Optional[Path] = None) -> None:
68
128
  base = experiments_dir or get_experiments_dir()
69
129
  directories = [
@@ -22,7 +22,7 @@ class DatabricksInitResult:
22
22
  "CR_CATALOG": self.catalog,
23
23
  "CR_SCHEMA": self.schema,
24
24
  "CR_EXPERIMENT_NAME": self.experiment_name,
25
- "CR_EXPERIMENTS_DIR": f"/Workspace/{self.workspace_path}/experiments" if self.workspace_path else "",
25
+ "CR_EXPERIMENTS_DIR": f"/Volumes/{self.catalog}/{self.schema}/experiments",
26
26
  }
27
27
  if self.workspace_path:
28
28
  env_vars["CR_WORKSPACE_PATH"] = self.workspace_path
@@ -38,10 +38,16 @@ def databricks_init(
38
38
  model_name: str = "customer_retention",
39
39
  ) -> DatabricksInitResult:
40
40
  _validate_databricks_environment()
41
+ if workspace_path:
42
+ workspace_path = _normalize_workspace_path(workspace_path)
43
+ _ensure_workspace_directory(workspace_path)
41
44
  _set_environment_variables(catalog, schema, workspace_path)
45
+ _persist_config(catalog, schema, workspace_path)
42
46
  resolved_experiment_name = experiment_name or _resolve_experiment_name_from_notebook_path()
43
47
  resolved_experiment_name = _make_absolute_experiment_path(resolved_experiment_name, workspace_path)
44
48
  _set_experiment_name_env_var(resolved_experiment_name)
49
+ _reload_config_constants()
50
+ _setup_experiment_directories()
45
51
  _configure_mlflow_experiment(resolved_experiment_name)
46
52
  notebooks_copied: list[str] = []
47
53
  if copy_notebooks and workspace_path:
@@ -69,15 +75,36 @@ def _validate_databricks_environment() -> None:
69
75
  def _set_environment_variables(catalog: str, schema: str, workspace_path: str | None) -> None:
70
76
  os.environ["CR_CATALOG"] = catalog
71
77
  os.environ["CR_SCHEMA"] = schema
78
+ os.environ["CR_EXPERIMENTS_DIR"] = f"/Volumes/{catalog}/{schema}/experiments"
72
79
  if workspace_path:
73
80
  os.environ["CR_WORKSPACE_PATH"] = workspace_path
74
- os.environ["CR_EXPERIMENTS_DIR"] = f"/Workspace/{workspace_path}/experiments"
75
81
 
76
82
 
77
83
  def _set_experiment_name_env_var(experiment_name: str) -> None:
78
84
  os.environ["CR_EXPERIMENT_NAME"] = experiment_name
79
85
 
80
86
 
87
+ def _persist_config(catalog: str, schema: str, workspace_path: str | None) -> None:
88
+ from customer_retention.core.config.experiments import persist_databricks_config
89
+
90
+ persist_databricks_config(f"/Volumes/{catalog}/{schema}/experiments", catalog, schema, workspace_path)
91
+
92
+
93
+ def _reload_config_constants() -> None:
94
+ from customer_retention.core.config.experiments import reload_config
95
+
96
+ reload_config()
97
+
98
+
99
+ def _setup_experiment_directories() -> None:
100
+ from customer_retention.core.config.experiments import setup_experiments_structure
101
+
102
+ try:
103
+ setup_experiments_structure()
104
+ except OSError:
105
+ pass
106
+
107
+
81
108
  def _resolve_experiment_name_from_notebook_path() -> str:
82
109
  try:
83
110
  dbutils = _get_dbutils()
@@ -98,6 +125,12 @@ def _get_dbutils() -> Any | None:
98
125
  return None
99
126
 
100
127
 
128
+ def _normalize_workspace_path(workspace_path: str) -> str:
129
+ if workspace_path.startswith("/Workspace/"):
130
+ return workspace_path[len("/Workspace/"):]
131
+ return workspace_path
132
+
133
+
101
134
  def _make_absolute_experiment_path(experiment_name: str, workspace_path: str | None) -> str:
102
135
  if experiment_name.startswith("/"):
103
136
  return experiment_name
@@ -118,6 +151,13 @@ def _configure_mlflow_experiment(experiment_name: str) -> None:
118
151
  pass
119
152
 
120
153
 
154
+ def _ensure_workspace_directory(workspace_path: str) -> None:
155
+ try:
156
+ Path(f"/Workspace/{workspace_path}").mkdir(parents=True, exist_ok=True)
157
+ except OSError:
158
+ pass
159
+
160
+
121
161
  def _copy_exploration_notebooks(workspace_path: str) -> list[str]:
122
162
  from customer_retention.generators.notebook_generator.project_init import ProjectInitializer
123
163
 
@@ -139,11 +179,14 @@ def _copy_exploration_notebooks(workspace_path: str) -> list[str]:
139
179
 
140
180
 
141
181
  def _display_init_summary(result: DatabricksInitResult) -> None:
142
- print("ChurnKit Databricks Initialization Complete")
182
+ from customer_retention import __version__
183
+
184
+ print(f"ChurnKit v{__version__} Databricks Initialization Complete")
143
185
  print("=" * 45)
144
186
  print(f" Catalog: {result.catalog}")
145
187
  print(f" Schema: {result.schema}")
146
188
  print(f" Experiment: {result.experiment_name}")
189
+ print(f" Experiments Dir: /Volumes/{result.catalog}/{result.schema}/experiments")
147
190
  print(f" Workspace Path: {result.workspace_path or '(not set)'}")
148
191
  print(f" Model Name: {result.model_name}")
149
192
  if result.notebooks_copied:
File without changes
File without changes
File without changes