openretailscience 0.45.0__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 (261) hide show
  1. openretailscience-0.45.0/.claude/commands/review-pr-tests.md +607 -0
  2. openretailscience-0.45.0/.env_sample +9 -0
  3. openretailscience-0.45.0/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  4. openretailscience-0.45.0/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. openretailscience-0.45.0/.github/dependabot.yml +15 -0
  6. openretailscience-0.45.0/.github/workflows/bigquery-integration.yml +67 -0
  7. openretailscience-0.45.0/.github/workflows/claude-code-review.yml +55 -0
  8. openretailscience-0.45.0/.github/workflows/claude.yml +112 -0
  9. openretailscience-0.45.0/.github/workflows/cloudflare-docs-preview.yml +99 -0
  10. openretailscience-0.45.0/.github/workflows/gh-page.yml +45 -0
  11. openretailscience-0.45.0/.github/workflows/pyspark-integration.yml +63 -0
  12. openretailscience-0.45.0/.github/workflows/release.yml +220 -0
  13. openretailscience-0.45.0/.github/workflows/slack-notifications.yml +103 -0
  14. openretailscience-0.45.0/.github/workflows/snowflake-integration.yml +86 -0
  15. openretailscience-0.45.0/.github/workflows/test.yml +75 -0
  16. openretailscience-0.45.0/.gitignore +144 -0
  17. openretailscience-0.45.0/.markdownlint.json +10 -0
  18. openretailscience-0.45.0/.pre-commit-config.yaml +56 -0
  19. openretailscience-0.45.0/CLAUDE.md +154 -0
  20. openretailscience-0.45.0/CNAME +1 -0
  21. openretailscience-0.45.0/CODE_OF_CONDUCT.md +127 -0
  22. openretailscience-0.45.0/CONTRIBUTING.md +51 -0
  23. openretailscience-0.45.0/LICENSE +93 -0
  24. openretailscience-0.45.0/PKG-INFO +364 -0
  25. openretailscience-0.45.0/README.md +335 -0
  26. openretailscience-0.45.0/data/transactions.parquet +0 -0
  27. openretailscience-0.45.0/docs/analysis_modules.md +1688 -0
  28. openretailscience-0.45.0/docs/api/analysis/cohort.md +3 -0
  29. openretailscience-0.45.0/docs/api/analysis/composite_rank.md +3 -0
  30. openretailscience-0.45.0/docs/api/analysis/cross_shop.md +3 -0
  31. openretailscience-0.45.0/docs/api/analysis/customer.md +3 -0
  32. openretailscience-0.45.0/docs/api/analysis/customer_decision_hierarchy.md +3 -0
  33. openretailscience-0.45.0/docs/api/analysis/gain_loss.md +3 -0
  34. openretailscience-0.45.0/docs/api/analysis/haversine.md +3 -0
  35. openretailscience-0.45.0/docs/api/analysis/product_association.md +3 -0
  36. openretailscience-0.45.0/docs/api/analysis/revenue_tree.md +3 -0
  37. openretailscience-0.45.0/docs/api/metrics/distribution.md +5 -0
  38. openretailscience-0.45.0/docs/api/options.md +3 -0
  39. openretailscience-0.45.0/docs/api/plots/area.md +3 -0
  40. openretailscience-0.45.0/docs/api/plots/bar.md +3 -0
  41. openretailscience-0.45.0/docs/api/plots/broken_timeline.md +3 -0
  42. openretailscience-0.45.0/docs/api/plots/cohort.md +3 -0
  43. openretailscience-0.45.0/docs/api/plots/heatmap.md +3 -0
  44. openretailscience-0.45.0/docs/api/plots/histogram.md +3 -0
  45. openretailscience-0.45.0/docs/api/plots/index.md +3 -0
  46. openretailscience-0.45.0/docs/api/plots/line.md +3 -0
  47. openretailscience-0.45.0/docs/api/plots/period_on_period.md +3 -0
  48. openretailscience-0.45.0/docs/api/plots/price.md +3 -0
  49. openretailscience-0.45.0/docs/api/plots/scatter.md +3 -0
  50. openretailscience-0.45.0/docs/api/plots/styles/graph_utils.md +3 -0
  51. openretailscience-0.45.0/docs/api/plots/styles/styling_helpers.md +3 -0
  52. openretailscience-0.45.0/docs/api/plots/time.md +3 -0
  53. openretailscience-0.45.0/docs/api/plots/venn.md +3 -0
  54. openretailscience-0.45.0/docs/api/plots/waterfall.md +3 -0
  55. openretailscience-0.45.0/docs/api/segmentation/hml.md +3 -0
  56. openretailscience-0.45.0/docs/api/segmentation/nlr.md +3 -0
  57. openretailscience-0.45.0/docs/api/segmentation/rfm.md +3 -0
  58. openretailscience-0.45.0/docs/api/segmentation/segstats.md +3 -0
  59. openretailscience-0.45.0/docs/api/segmentation/threshold.md +3 -0
  60. openretailscience-0.45.0/docs/api/utils/date.md +3 -0
  61. openretailscience-0.45.0/docs/api/utils/filter_and_label.md +3 -0
  62. openretailscience-0.45.0/docs/api/utils/label.md +3 -0
  63. openretailscience-0.45.0/docs/assets/gallery/area_thumbnail.png +0 -0
  64. openretailscience-0.45.0/docs/assets/gallery/bar_thumbnail.png +0 -0
  65. openretailscience-0.45.0/docs/assets/gallery/broken_timeline_thumbnail.png +0 -0
  66. openretailscience-0.45.0/docs/assets/gallery/cohort_thumbnail.png +0 -0
  67. openretailscience-0.45.0/docs/assets/gallery/heatmap_thumbnail.png +0 -0
  68. openretailscience-0.45.0/docs/assets/gallery/histogram_thumbnail.png +0 -0
  69. openretailscience-0.45.0/docs/assets/gallery/index_thumbnail.png +0 -0
  70. openretailscience-0.45.0/docs/assets/gallery/line_thumbnail.png +0 -0
  71. openretailscience-0.45.0/docs/assets/gallery/period_on_period_thumbnail.png +0 -0
  72. openretailscience-0.45.0/docs/assets/gallery/price_thumbnail.png +0 -0
  73. openretailscience-0.45.0/docs/assets/gallery/scatter_thumbnail.png +0 -0
  74. openretailscience-0.45.0/docs/assets/gallery/time_thumbnail.png +0 -0
  75. openretailscience-0.45.0/docs/assets/gallery/venn_thumbnail.png +0 -0
  76. openretailscience-0.45.0/docs/assets/gallery/waterfall_thumbnail.png +0 -0
  77. openretailscience-0.45.0/docs/assets/images/analysis_modules/cross_shop.svg +1997 -0
  78. openretailscience-0.45.0/docs/assets/images/analysis_modules/customer_decision_hierarchy.svg +2795 -0
  79. openretailscience-0.45.0/docs/assets/images/analysis_modules/days_between_purchases.svg +2431 -0
  80. openretailscience-0.45.0/docs/assets/images/analysis_modules/gain_loss.svg +2160 -0
  81. openretailscience-0.45.0/docs/assets/images/analysis_modules/hml_segmentation.svg +1629 -0
  82. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/area.svg +2145 -0
  83. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/bar_plot.svg +2443 -0
  84. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/broken_timeline.svg +2015 -0
  85. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/cohort.svg +4454 -0
  86. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/heatmap.svg +3531 -0
  87. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/histogram_plot.svg +2453 -0
  88. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/index_plot.svg +2263 -0
  89. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/line_plot.svg +2025 -0
  90. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/period_on_period.svg +2177 -0
  91. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/price_plot.svg +2746 -0
  92. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/scatter.svg +2373 -0
  93. openretailscience-0.45.0/docs/assets/images/analysis_modules/plots/venn.svg +2177 -0
  94. openretailscience-0.45.0/docs/assets/images/analysis_modules/purchases_per_customer.svg +2065 -0
  95. openretailscience-0.45.0/docs/assets/images/analysis_modules/revenue_tree.svg +2712 -0
  96. openretailscience-0.45.0/docs/assets/images/analysis_modules/threshold_segmentation.svg +1750 -0
  97. openretailscience-0.45.0/docs/assets/images/analysis_modules/time_plot.svg +1 -0
  98. openretailscience-0.45.0/docs/assets/images/analysis_modules/transaction_churn.svg +2074 -0
  99. openretailscience-0.45.0/docs/assets/images/analysis_modules/waterfall.svg +1854 -0
  100. openretailscience-0.45.0/docs/assets/images/favicon.svg +66 -0
  101. openretailscience-0.45.0/docs/assets/images/features/charts.png +0 -0
  102. openretailscience-0.45.0/docs/assets/images/features/cross_shop.png +0 -0
  103. openretailscience-0.45.0/docs/assets/images/logo.svg +22 -0
  104. openretailscience-0.45.0/docs/examples/cross_shop.ipynb +988 -0
  105. openretailscience-0.45.0/docs/examples/gain_loss.ipynb +887 -0
  106. openretailscience-0.45.0/docs/examples/product_association.ipynb +685 -0
  107. openretailscience-0.45.0/docs/examples/retention.ipynb +456 -0
  108. openretailscience-0.45.0/docs/examples/revenue_tree.ipynb +307 -0
  109. openretailscience-0.45.0/docs/examples/segmentation.ipynb +854 -0
  110. openretailscience-0.45.0/docs/gallery/index.md +199 -0
  111. openretailscience-0.45.0/docs/gallery/plots/area.ipynb +412 -0
  112. openretailscience-0.45.0/docs/gallery/plots/bar.ipynb +568 -0
  113. openretailscience-0.45.0/docs/gallery/plots/broken_timeline.ipynb +284 -0
  114. openretailscience-0.45.0/docs/gallery/plots/cohort.ipynb +161 -0
  115. openretailscience-0.45.0/docs/gallery/plots/heatmap.ipynb +155 -0
  116. openretailscience-0.45.0/docs/gallery/plots/histogram.ipynb +209 -0
  117. openretailscience-0.45.0/docs/gallery/plots/index_plot.ipynb +701 -0
  118. openretailscience-0.45.0/docs/gallery/plots/line.ipynb +428 -0
  119. openretailscience-0.45.0/docs/gallery/plots/period_on_period.ipynb +153 -0
  120. openretailscience-0.45.0/docs/gallery/plots/price.ipynb +176 -0
  121. openretailscience-0.45.0/docs/gallery/plots/scatter.ipynb +199 -0
  122. openretailscience-0.45.0/docs/gallery/plots/time.ipynb +247 -0
  123. openretailscience-0.45.0/docs/gallery/plots/venn.ipynb +239 -0
  124. openretailscience-0.45.0/docs/gallery/plots/waterfall.ipynb +266 -0
  125. openretailscience-0.45.0/docs/getting_started/installation.md +16 -0
  126. openretailscience-0.45.0/docs/getting_started/options_guide.md +416 -0
  127. openretailscience-0.45.0/docs/index.md +9 -0
  128. openretailscience-0.45.0/docs/javascripts/mathjax.js +19 -0
  129. openretailscience-0.45.0/docs/metrics.md +85 -0
  130. openretailscience-0.45.0/docs/overrides/home.html +232 -0
  131. openretailscience-0.45.0/docs/overrides/main.html +7 -0
  132. openretailscience-0.45.0/docs/robots.txt +5 -0
  133. openretailscience-0.45.0/docs/stylesheets/extra.css +915 -0
  134. openretailscience-0.45.0/mkdocs.yml +151 -0
  135. openretailscience-0.45.0/openretailscience/__init__.py +3 -0
  136. openretailscience-0.45.0/openretailscience/analysis/__init__.py +0 -0
  137. openretailscience-0.45.0/openretailscience/analysis/cohort.py +185 -0
  138. openretailscience-0.45.0/openretailscience/analysis/composite_rank.py +372 -0
  139. openretailscience-0.45.0/openretailscience/analysis/cross_shop.py +354 -0
  140. openretailscience-0.45.0/openretailscience/analysis/customer.py +459 -0
  141. openretailscience-0.45.0/openretailscience/analysis/customer_decision_hierarchy.py +359 -0
  142. openretailscience-0.45.0/openretailscience/analysis/gain_loss.py +340 -0
  143. openretailscience-0.45.0/openretailscience/analysis/haversine.py +50 -0
  144. openretailscience-0.45.0/openretailscience/analysis/product_association.py +418 -0
  145. openretailscience-0.45.0/openretailscience/analysis/revenue_tree.py +553 -0
  146. openretailscience-0.45.0/openretailscience/assets/fonts/Poppins-Bold.ttf +0 -0
  147. openretailscience-0.45.0/openretailscience/assets/fonts/Poppins-LightItalic.ttf +0 -0
  148. openretailscience-0.45.0/openretailscience/assets/fonts/Poppins-Medium.ttf +0 -0
  149. openretailscience-0.45.0/openretailscience/assets/fonts/Poppins-Regular.ttf +0 -0
  150. openretailscience-0.45.0/openretailscience/assets/fonts/Poppins-SemiBold.ttf +0 -0
  151. openretailscience-0.45.0/openretailscience/constants.py +295 -0
  152. openretailscience-0.45.0/openretailscience/metrics/__init__.py +0 -0
  153. openretailscience-0.45.0/openretailscience/metrics/base.py +29 -0
  154. openretailscience-0.45.0/openretailscience/metrics/distribution/__init__.py +0 -0
  155. openretailscience-0.45.0/openretailscience/metrics/distribution/acv.py +81 -0
  156. openretailscience-0.45.0/openretailscience/metrics/distribution/pct_of_stores.py +118 -0
  157. openretailscience-0.45.0/openretailscience/options.py +842 -0
  158. openretailscience-0.45.0/openretailscience/plots/__init__.py +0 -0
  159. openretailscience-0.45.0/openretailscience/plots/area.py +114 -0
  160. openretailscience-0.45.0/openretailscience/plots/bar.py +375 -0
  161. openretailscience-0.45.0/openretailscience/plots/broken_timeline.py +197 -0
  162. openretailscience-0.45.0/openretailscience/plots/cohort.py +94 -0
  163. openretailscience-0.45.0/openretailscience/plots/heatmap.py +134 -0
  164. openretailscience-0.45.0/openretailscience/plots/histogram.py +276 -0
  165. openretailscience-0.45.0/openretailscience/plots/index.py +505 -0
  166. openretailscience-0.45.0/openretailscience/plots/line.py +379 -0
  167. openretailscience-0.45.0/openretailscience/plots/period_on_period.py +144 -0
  168. openretailscience-0.45.0/openretailscience/plots/price.py +275 -0
  169. openretailscience-0.45.0/openretailscience/plots/scatter.py +382 -0
  170. openretailscience-0.45.0/openretailscience/plots/styles/__init__.py +1 -0
  171. openretailscience-0.45.0/openretailscience/plots/styles/colors.py +215 -0
  172. openretailscience-0.45.0/openretailscience/plots/styles/font_utils.py +62 -0
  173. openretailscience-0.45.0/openretailscience/plots/styles/graph_utils.py +834 -0
  174. openretailscience-0.45.0/openretailscience/plots/styles/styling_helpers.py +155 -0
  175. openretailscience-0.45.0/openretailscience/plots/time.py +160 -0
  176. openretailscience-0.45.0/openretailscience/plots/tree_diagram.py +813 -0
  177. openretailscience-0.45.0/openretailscience/plots/venn.py +127 -0
  178. openretailscience-0.45.0/openretailscience/plots/waterfall.py +217 -0
  179. openretailscience-0.45.0/openretailscience/plugin.py +238 -0
  180. openretailscience-0.45.0/openretailscience/segmentation/__init__.py +0 -0
  181. openretailscience-0.45.0/openretailscience/segmentation/hml.py +97 -0
  182. openretailscience-0.45.0/openretailscience/segmentation/nlr.py +218 -0
  183. openretailscience-0.45.0/openretailscience/segmentation/rfm.py +307 -0
  184. openretailscience-0.45.0/openretailscience/segmentation/segstats.py +1177 -0
  185. openretailscience-0.45.0/openretailscience/segmentation/threshold.py +165 -0
  186. openretailscience-0.45.0/openretailscience/utils/__init__.py +0 -0
  187. openretailscience-0.45.0/openretailscience/utils/date.py +226 -0
  188. openretailscience-0.45.0/openretailscience/utils/filter_and_label.py +52 -0
  189. openretailscience-0.45.0/openretailscience/utils/label.py +79 -0
  190. openretailscience-0.45.0/openretailscience/utils/validation.py +45 -0
  191. openretailscience-0.45.0/options_template.toml +77 -0
  192. openretailscience-0.45.0/pyproject.toml +166 -0
  193. openretailscience-0.45.0/readme_assets/cross_shop_chart.png +0 -0
  194. openretailscience-0.45.0/readme_assets/days_until_next_purchase.png +0 -0
  195. openretailscience-0.45.0/readme_assets/gain_loss_chart.png +0 -0
  196. openretailscience-0.45.0/readme_assets/logo.png +0 -0
  197. openretailscience-0.45.0/readme_assets/new_store_cannibalization.png +0 -0
  198. openretailscience-0.45.0/taplo.toml +33 -0
  199. openretailscience-0.45.0/tests/analysis/test_cohort.py +185 -0
  200. openretailscience-0.45.0/tests/analysis/test_composite_rank.py +584 -0
  201. openretailscience-0.45.0/tests/analysis/test_cross_shop.py +726 -0
  202. openretailscience-0.45.0/tests/analysis/test_customer.py +98 -0
  203. openretailscience-0.45.0/tests/analysis/test_customer_decision_hierarchy.py +153 -0
  204. openretailscience-0.45.0/tests/analysis/test_gain_loss.py +285 -0
  205. openretailscience-0.45.0/tests/analysis/test_haversine.py +35 -0
  206. openretailscience-0.45.0/tests/analysis/test_product_association.py +371 -0
  207. openretailscience-0.45.0/tests/analysis/test_revenue_tree.py +769 -0
  208. openretailscience-0.45.0/tests/integration/conftest.py +47 -0
  209. openretailscience-0.45.0/tests/integration/test_cohort_analysis.py +29 -0
  210. openretailscience-0.45.0/tests/integration/test_composite_rank.py +32 -0
  211. openretailscience-0.45.0/tests/integration/test_cross_shop.py +58 -0
  212. openretailscience-0.45.0/tests/integration/test_customer_decision_hierarchy.py +42 -0
  213. openretailscience-0.45.0/tests/integration/test_date.py +29 -0
  214. openretailscience-0.45.0/tests/integration/test_filter_and_label.py +29 -0
  215. openretailscience-0.45.0/tests/integration/test_haversine.py +26 -0
  216. openretailscience-0.45.0/tests/integration/test_hml_segmentation.py +38 -0
  217. openretailscience-0.45.0/tests/integration/test_product_association.py +41 -0
  218. openretailscience-0.45.0/tests/integration/test_revenue_tree.py +62 -0
  219. openretailscience-0.45.0/tests/integration/test_rfm_segmentation.py +72 -0
  220. openretailscience-0.45.0/tests/integration/test_segstats_segmentation.py +75 -0
  221. openretailscience-0.45.0/tests/integration/test_threshold_segmentation.py +43 -0
  222. openretailscience-0.45.0/tests/metrics/distribution/test_acv.py +121 -0
  223. openretailscience-0.45.0/tests/metrics/distribution/test_pct_of_stores.py +267 -0
  224. openretailscience-0.45.0/tests/metrics/test_base.py +63 -0
  225. openretailscience-0.45.0/tests/plots/styles/test_color.py +127 -0
  226. openretailscience-0.45.0/tests/plots/styles/test_font_utils.py +39 -0
  227. openretailscience-0.45.0/tests/plots/styles/test_graph_utils.py +934 -0
  228. openretailscience-0.45.0/tests/plots/styles/test_styling_helper.py +114 -0
  229. openretailscience-0.45.0/tests/plots/test_area.py +153 -0
  230. openretailscience-0.45.0/tests/plots/test_bar.py +528 -0
  231. openretailscience-0.45.0/tests/plots/test_broken_timeline.py +351 -0
  232. openretailscience-0.45.0/tests/plots/test_cohort.py +163 -0
  233. openretailscience-0.45.0/tests/plots/test_heatmap.py +246 -0
  234. openretailscience-0.45.0/tests/plots/test_histogram.py +343 -0
  235. openretailscience-0.45.0/tests/plots/test_index.py +983 -0
  236. openretailscience-0.45.0/tests/plots/test_line.py +649 -0
  237. openretailscience-0.45.0/tests/plots/test_period_on_period.py +144 -0
  238. openretailscience-0.45.0/tests/plots/test_price.py +548 -0
  239. openretailscience-0.45.0/tests/plots/test_scatter.py +762 -0
  240. openretailscience-0.45.0/tests/plots/test_styling_options_integration.py +216 -0
  241. openretailscience-0.45.0/tests/plots/test_time.py +94 -0
  242. openretailscience-0.45.0/tests/plots/test_tree_diagram.py +827 -0
  243. openretailscience-0.45.0/tests/plots/test_venn.py +100 -0
  244. openretailscience-0.45.0/tests/plots/test_waterfall.py +186 -0
  245. openretailscience-0.45.0/tests/segmentation/test_hml.py +222 -0
  246. openretailscience-0.45.0/tests/segmentation/test_nlr.py +393 -0
  247. openretailscience-0.45.0/tests/segmentation/test_rfm.py +482 -0
  248. openretailscience-0.45.0/tests/segmentation/test_segstats.py +2108 -0
  249. openretailscience-0.45.0/tests/segmentation/test_threshold.py +293 -0
  250. openretailscience-0.45.0/tests/test_options.py +267 -0
  251. openretailscience-0.45.0/tests/test_plugin.py +367 -0
  252. openretailscience-0.45.0/tests/toml_files/corrupt.toml +1 -0
  253. openretailscience-0.45.0/tests/toml_files/invalid_option.toml +3 -0
  254. openretailscience-0.45.0/tests/toml_files/test_options.toml +42 -0
  255. openretailscience-0.45.0/tests/toml_files/valid.toml +12 -0
  256. openretailscience-0.45.0/tests/utils/test_date.py +393 -0
  257. openretailscience-0.45.0/tests/utils/test_filter_and_label.py +71 -0
  258. openretailscience-0.45.0/tests/utils/test_label.py +173 -0
  259. openretailscience-0.45.0/tests/utils/test_validation.py +87 -0
  260. openretailscience-0.45.0/tox.ini +17 -0
  261. openretailscience-0.45.0/uv.lock +3757 -0
@@ -0,0 +1,607 @@
1
+ # Input Validation
2
+ if [ -z "$1" ]; then
3
+ echo "Error: PR number is required. Usage: /review-pr-tests <PR_NUMBER>"
4
+ exit 1
5
+ fi
6
+
7
+ You are reviewing all Python tests in PR #$1 for the OpenRetailScience package.
8
+
9
+ ## Initial Analysis Steps:
10
+ 1. **First, check the PR using `gh pr view $1` and `gh pr diff $1`** to see the changes
11
+ 2. **If you need to examine test files locally**, check out the PR:
12
+ ```bash
13
+ # This automatically fetches and checks out the PR's branch
14
+ # (handles both local and remote branches)
15
+ gh pr checkout $1
16
+ ```
17
+ 3. **Check if there are any Python test files** in the PR (files matching `test_*.py` or `*_test.py`). If no test files exist, provide a brief note about missing tests
18
+ 4. **Identify which OpenRetailScience module is being tested** by analyzing the imports and function calls in the code
19
+
20
+ If there are no test files in the PR, respond with:
21
+ ```
22
+ ## NO TEST FILES FOUND IN PR #$1
23
+
24
+ This PR does not contain any test files. Consider adding tests for:
25
+ - [List key functionality that should be tested based on the PR changes]
26
+ ```
27
+
28
+ Otherwise, identify tests that fall into the following problematic categories:
29
+
30
+ ## 1. Tests That Don't Test Package Code
31
+ Tests that make assertions but never call any functions, classes, or modules from the package under test. Look for tests that only test local variables, Python built-ins, or standard library functions without involving the actual package.
32
+
33
+ **Red Flags:**
34
+ - No imports from the package being tested
35
+ - Only tests variable assignments or basic Python operations
36
+ - Never calls functions/methods from the package
37
+
38
+ **Example:**
39
+ ```python
40
+ def test_basic_math():
41
+ # BAD: Never uses the package under test
42
+ x = 1
43
+ y = 2
44
+ assert x + y == 3
45
+
46
+ def test_string_operations():
47
+ # BAD: Only tests Python built-in string methods
48
+ name = "John"
49
+ assert name.upper() == "JOHN"
50
+ assert len(name) == 4
51
+ ```
52
+
53
+ ## 2. Tests That Primarily Test Library Functionality
54
+ Tests that focus on verifying external library behavior rather than how the package under test uses those libraries. These tests essentially re-test third-party libraries that should already have their own test suites.
55
+
56
+ **Red Flags:**
57
+ - Directly calls library functions without package wrapper
58
+ - Tests properties of library outputs (e.g., UUID format, datetime formatting)
59
+ - Could be moved to the library's own test suite without loss
60
+
61
+ **Example:**
62
+ ```python
63
+ import uuid
64
+ import pandas as pd
65
+ from datetime import datetime
66
+
67
+ def test_uuid_generation():
68
+ # BAD: Tests uuid library, not the package's use of it
69
+ generated_id = str(uuid.uuid4())
70
+ assert len(generated_id) == 36
71
+ assert generated_id.count("-") == 4
72
+
73
+ def test_pandas_dataframe():
74
+ # BAD: Tests pandas functionality, not package code
75
+ df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
76
+ assert len(df) == 2
77
+ assert 'A' in df.columns
78
+
79
+ # GOOD: Tests package's use of the library
80
+ def test_crossshop_analysis():
81
+ from openretailscience.crossshop import CrossShop
82
+ analyzer = CrossShop(store_col="store_id")
83
+ result = analyzer.fit(df)
84
+ assert result.shape[0] > 0 # Tests that package processes data
85
+ assert "customer_id" in result.columns # Tests package output
86
+ ```
87
+
88
+ ## 3. Tests With Substantial Duplication
89
+ Tests that repeat significant portions of logic, assertions, or setup from other tests without adding meaningful coverage. Look for copy-pasted test code with minor variations that don't test different behavior.
90
+
91
+ **Red Flags:**
92
+ - Multiple tests with nearly identical setup code
93
+ - Same assertions repeated across tests with minor value changes
94
+ - Tests that differ only in input values but test the same code path
95
+ - Could be combined using parametrize or merged into one test
96
+
97
+ **Example:**
98
+ ```python
99
+ def test_add_positive_numbers():
100
+ calc = Calculator()
101
+ result = calc.add(5, 3)
102
+ assert result == 8
103
+ assert result > 0
104
+ assert isinstance(result, int)
105
+
106
+ def test_add_different_positive_numbers():
107
+ # BAD: Duplicates above test with different values
108
+ calc = Calculator()
109
+ result = calc.add(10, 7)
110
+ assert result == 17
111
+ assert result > 0
112
+ assert isinstance(result, int)
113
+
114
+ def test_add_more_numbers():
115
+ # BAD: Same pattern again
116
+ calc = Calculator()
117
+ result = calc.add(2, 4)
118
+ assert result == 6
119
+ assert result > 0
120
+ assert isinstance(result, int)
121
+
122
+ # BETTER: Use parametrize or combine into one comprehensive test
123
+ @pytest.mark.parametrize("a,b,expected", [
124
+ (5, 3, 8),
125
+ (10, 7, 17),
126
+ (2, 4, 6)
127
+ ])
128
+ def test_add_positive_numbers(a, b, expected):
129
+ calc = Calculator()
130
+ result = calc.add(a, b)
131
+ assert result == expected
132
+ assert result > 0
133
+ assert isinstance(result, int)
134
+ ```
135
+
136
+ ## 4. Tests That Cover Only Basic Language/Library Features
137
+ Tests that verify fundamental Python or standard library behavior without meaningful connection to OpenRetailScience's functionality. These tests essentially verify that Python works as expected.
138
+
139
+ **Red Flags:**
140
+ - Tests basic Python operations (list, dict, set operations)
141
+ - Verifies standard library behavior that's guaranteed by Python
142
+ - No connection to business logic or package functionality
143
+ - Could be in Python's own test suite
144
+
145
+ **Example:**
146
+ ```python
147
+ def test_basic_set_operations():
148
+ # BAD: Tests Python's set behavior
149
+ assert len(set(["Hello", "World"])) == 2
150
+ assert "Hello" in set(["Hello", "World"])
151
+
152
+ def test_dictionary_basics():
153
+ # BAD: Tests Python dict functionality
154
+ d = {"key": "value"}
155
+ assert d.get("key") == "value"
156
+ assert d.get("missing", "default") == "default"
157
+
158
+ def test_list_operations():
159
+ # BAD: Tests Python list methods
160
+ items = [1, 2, 3]
161
+ items.append(4)
162
+ assert len(items) == 4
163
+ assert items[-1] == 4
164
+ ```
165
+
166
+ ## Additional Problematic Patterns to Identify:
167
+
168
+ ### 5. Trivial or Tautological Tests
169
+ Tests that assert obvious truths, constants equal themselves, or test definitions rather than behavior. These provide no value and false confidence in coverage metrics.
170
+
171
+ **Red Flags:**
172
+ - Tests that a constant equals its defined value
173
+ - Assertions that are always true by definition
174
+ - Tests that verify class/function names or attributes exist
175
+ - No actual behavior or logic being tested
176
+
177
+ **Example:**
178
+ ```python
179
+ # Assuming MAX_STORES = 100 in openretailscience.config
180
+ def test_constant():
181
+ from openretailscience.config import MAX_STORES
182
+ # BAD: Just tests that 100 == 100
183
+ assert MAX_STORES == 100
184
+
185
+ def test_true_is_true():
186
+ # BAD: Tautological
187
+ assert True == True
188
+ assert 1 == 1
189
+
190
+ def test_class_name():
191
+ from openretailscience.style import BaseStyle
192
+ # BAD: Tests Python's class system, not package behavior
193
+ obj = BaseStyle()
194
+ assert obj.__class__.__name__ == "BaseStyle"
195
+
196
+ def test_config_values():
197
+ # BAD if CONFIG is just {"debug": False}
198
+ from openretailscience import CONFIG
199
+ assert CONFIG["debug"] == False # Just repeating the definition
200
+ ```
201
+
202
+ ### 6. Tests With No Meaningful Assertions
203
+ Tests that either have no assertions, only assert True, or have assertions that can never fail. These tests may execute code but don't verify behavior or outcomes.
204
+
205
+ **Red Flags:**
206
+ - No assert statements at all
207
+ - Only checks if attributes/methods exist
208
+ - Assertions that can never fail given the test setup
209
+ - Tests that only verify successful execution without checking results
210
+
211
+ **Example:**
212
+ ```python
213
+ def test_function_runs():
214
+ from openretailscience.segmentation import RFM
215
+ # BAD: No assertions
216
+ rfm = RFM()
217
+ rfm.fit(df)
218
+ # Test passes even if function does nothing or fails silently
219
+
220
+ def test_function_exists():
221
+ import openretailscience.style
222
+ # BAD: Only tests existence, not behavior
223
+ assert hasattr(openretailscience.style, 'apply_style')
224
+ assert callable(openretailscience.style.apply_style)
225
+
226
+ def test_always_passes():
227
+ from openretailscience.customer_choice import ProductAssociation
228
+ # BAD: Assertion can never fail
229
+ pa = ProductAssociation()
230
+ confidence = pa.get_confidence()
231
+ assert confidence >= 0 or confidence < 0 # Always true for any number
232
+
233
+ def test_object_creation():
234
+ from openretailscience.pricing import PriceElasticity
235
+ # BAD: Only tests that no exception is raised
236
+ obj = PriceElasticity()
237
+ assert obj is not None # Objects are never None after creation
238
+
239
+ # GOOD: Test actual behavior
240
+ def test_rfm_segmentation():
241
+ from openretailscience.segmentation import RFM
242
+ rfm = RFM()
243
+ result = rfm.fit_predict(df)
244
+ assert 'segment' in result.columns # Verifies actual output
245
+ assert len(result) == len(df) # Verifies processing
246
+ ```
247
+
248
+ ### 7. Over-Mocked Tests
249
+ Tests that mock so extensively that they don't actually test real behavior or integration. When everything is mocked, you're only testing that mocks return what you told them to return.
250
+
251
+ **Red Flags:**
252
+ - Mocks every external dependency AND internal components
253
+ - Test would pass even if the actual implementation is completely broken
254
+ - Mocks return values that are directly asserted
255
+ - No real code execution happening
256
+ - More mock setup than actual test code
257
+
258
+ **Example:**
259
+ ```python
260
+ def test_crossshop_analysis(mocker):
261
+ from openretailscience.crossshop import CrossShop
262
+ # BAD: Mocks everything, tests nothing real
263
+ mocker.patch('openretailscience.crossshop._validate_data', return_value=True)
264
+ mocker.patch('openretailscience.crossshop._calculate_matrix', return_value=pd.DataFrame())
265
+ mocker.patch('openretailscience.crossshop._apply_filters', return_value=pd.DataFrame())
266
+ mocker.patch('openretailscience.crossshop._format_output', return_value={'result': 'done'})
267
+
268
+ cs = CrossShop()
269
+ result = cs.fit(df)
270
+ assert result == {'result': 'done'} # Only tests that mock returns 'done'
271
+
272
+ def test_pricing_optimization(mocker):
273
+ from openretailscience.pricing import optimize_prices
274
+ # BAD: Nothing real is tested
275
+ mocker.patch('openretailscience.pricing.validate_input', return_value=True)
276
+ mocker.patch('openretailscience.pricing.calculate_elasticity', return_value=1.5)
277
+ mocker.patch('openretailscience.pricing.find_optimal', return_value=99.99)
278
+ mocker.patch('openretailscience.pricing.apply_constraints', return_value=95.00)
279
+
280
+ result = optimize_prices(product_data)
281
+ assert result == 95.00 # Just testing mock configuration
282
+
283
+ # GOOD: Mock external dependencies but test real logic
284
+ def test_rfm_with_real_calculation(mocker):
285
+ from openretailscience.segmentation import RFM
286
+ # Mock only data loading, not the actual RFM logic
287
+ mocker.patch('openretailscience.segmentation.load_data', return_value=test_df)
288
+
289
+ # Test real RFM calculation logic
290
+ rfm = RFM()
291
+ result = rfm.calculate_scores(test_df)
292
+ assert 'R_score' in result.columns # Tests real scoring logic
293
+ ```
294
+
295
+ ### 8. Tests That Verify Implementation Details
296
+ Tests that check internal data structures, state, or "how" something works rather than "what" it produces. These tests break when refactoring even if the public behavior remains correct. Note: Testing private method BEHAVIOR (outputs) is often acceptable for complex algorithms.
297
+
298
+ **Red Flags:**
299
+ - Tests internal data structures or formats
300
+ - Verifies private attributes that track internal state
301
+ - Checks exact method call sequences or execution paths
302
+ - Tests "how" rather than "what"
303
+ - Would break if you change implementation but keep same behavior
304
+
305
+ **Key Distinction:**
306
+ - **BAD**: Testing internal state/structure → `assert obj._cache == {...}`
307
+ - **OK**: Testing private method behavior → `assert obj._calculate(5) == 10`
308
+
309
+ **Example:**
310
+ ```python
311
+ def test_internal_cache_structure():
312
+ from openretailscience.style import StyleCache
313
+ # BAD: Tests internal data structure/state
314
+ cache = StyleCache()
315
+ cache.add_style("retail", {"color": "blue"})
316
+
317
+ # Testing HOW data is stored internally
318
+ assert isinstance(cache._styles, dict)
319
+ assert len(cache._cache_keys) == 1
320
+ assert cache._counter == 1 # Private state tracking
321
+ assert cache._styles['retail']['format'] == 'processed'
322
+
323
+ def test_rfm_algorithm_internals():
324
+ from openretailscience.segmentation import RFM
325
+ # BAD: Tests HOW algorithm works internally
326
+ rfm = RFM()
327
+ rfm.fit(customer_data)
328
+
329
+ # Testing internal algorithm mechanics
330
+ assert rfm._percentile_breaks == [25, 50, 75]
331
+ assert rfm._score_mappings == {1: 'low', 2: 'med', 3: 'high'}
332
+ assert rfm._calculation_order == ['R', 'F', 'M']
333
+
334
+ def test_internal_validation_calls(mocker):
335
+ from openretailscience.crossshop import CrossShop
336
+ # BAD: Tests exact execution path
337
+ cs = CrossShop()
338
+ spy = mocker.spy(cs, '_validate_columns')
339
+
340
+ cs.fit(df)
341
+ spy.assert_called_once_with(df.columns) # Tests call sequence
342
+
343
+ # GOOD: Test behavior/output, even of private methods
344
+ def test_elasticity_calculation():
345
+ from openretailscience.pricing import PriceElasticity
346
+ # GOOD: Testing WHAT a private method produces
347
+ pe = PriceElasticity(base_price=100)
348
+ elasticity = pe._calculate_point_elasticity(95, 1000, 105, 900)
349
+ assert abs(elasticity + 2.0) < 0.01 # Tests mathematical correctness
350
+
351
+ def test_crossshop_matrix_output():
352
+ from openretailscience.crossshop import CrossShop
353
+ # GOOD: Tests public behavior
354
+ cs = CrossShop(store_col="store_id")
355
+ result = cs.create_matrix(transaction_data)
356
+ assert result.shape == (n_stores, n_stores) # Tests output structure
357
+ ```
358
+
359
+ ### 9. Tests That Could Use Parametrization
360
+ Multiple test functions that test the same behavior with different inputs but don't use pytest's parametrization feature. This leads to code duplication and harder maintenance.
361
+
362
+ **Use pytest.mark.parametrize for:**
363
+ - Tests with identical structure but different input values
364
+ - Multiple test cases that differ only in data
365
+ - Boundary value testing with multiple edge cases
366
+
367
+ **Red Flags:**
368
+ - Multiple test functions with identical structure
369
+ - Only differences are input values and expected outputs
370
+ - Same setup and assertion patterns
371
+ - Test names differ only by the values being tested
372
+ - Could be a single parametrized test
373
+
374
+ **Example:**
375
+ ```python
376
+ # BAD: Repetitive test functions
377
+ def test_divide_by_two():
378
+ assert calculator.divide(10, 2) == 5
379
+
380
+ def test_divide_by_five():
381
+ assert calculator.divide(20, 5) == 4
382
+
383
+ def test_divide_by_ten():
384
+ assert calculator.divide(100, 10) == 10
385
+
386
+ def test_divide_negative():
387
+ assert calculator.divide(-10, 2) == -5
388
+
389
+ def test_validate_email_gmail():
390
+ assert validator.is_valid("user@gmail.com") == True
391
+
392
+ def test_validate_email_yahoo():
393
+ assert validator.is_valid("user@yahoo.com") == True
394
+
395
+ def test_validate_email_invalid():
396
+ assert validator.is_valid("not-an-email") == False
397
+
398
+ # GOOD: Use parametrize
399
+ @pytest.mark.parametrize("dividend,divisor,expected", [
400
+ (10, 2, 5),
401
+ (20, 5, 4),
402
+ (100, 10, 10),
403
+ (-10, 2, -5),
404
+ ])
405
+ def test_divide(dividend, divisor, expected):
406
+ assert calculator.divide(dividend, divisor) == expected
407
+
408
+ @pytest.mark.parametrize("email,is_valid", [
409
+ ("user@gmail.com", True),
410
+ ("user@yahoo.com", True),
411
+ ("not-an-email", False),
412
+ ])
413
+ def test_validate_email(email, is_valid):
414
+ assert validator.is_valid(email) == is_valid
415
+ ```
416
+
417
+ ### 10. Tests With Generic or Non-Descriptive Test Data
418
+ Tests that use generic placeholder values (like "A", "B", "C", "test", "data", "123") instead of realistic, domain-specific examples that make the test's purpose and behavior clearer.
419
+
420
+ **Example:**
421
+ ```python
422
+ def test_rfm_segmentation():
423
+ # Generic, non-descriptive test data
424
+ customers = ["A", "B", "C"]
425
+ transactions = [
426
+ {"customer": "test", "amount": 100, "date": "2024-01-01"},
427
+ {"customer": "data", "amount": 200, "date": "2024-01-02"}
428
+ ]
429
+
430
+ rfm = RFM()
431
+ result = rfm.fit_predict(transactions)
432
+ assert "segment" in result.columns
433
+
434
+ # Better with realistic retail data:
435
+ def test_rfm_segmentation():
436
+ # Realistic retail customer data
437
+ transactions = [
438
+ {"customer_id": "CUST_10234", "amount": 156.99, "date": "2024-01-15", "store": "Store_001"},
439
+ {"customer_id": "CUST_10235", "amount": 89.50, "date": "2024-01-16", "store": "Store_002"},
440
+ {"customer_id": "CUST_10234", "amount": 234.75, "date": "2024-02-01", "store": "Store_001"}
441
+ ]
442
+
443
+ rfm = RFM()
444
+ result = rfm.fit_predict(pd.DataFrame(transactions))
445
+ assert "segment" in result.columns
446
+ ```
447
+
448
+ **Why this matters:**
449
+ - Realistic data makes tests easier to understand and relate to actual use cases
450
+ - Helps developers quickly grasp what the test is validating
451
+ - Makes debugging easier when tests fail
452
+ - Serves as implicit documentation of expected data formats and business logic
453
+ - Reduces cognitive load when reading and maintaining tests
454
+
455
+ ### 11. Tests That Don't Verify Their Claimed Behavior
456
+ Tests where the function name, docstring, or description claims to test specific behavior, but the assertions are too generic to actually verify that behavior. These tests create false confidence by appearing to test important functionality while only checking trivial outcomes.
457
+
458
+ **Red Flags:**
459
+ - Test name mentions specific behavior (e.g., "sorts", "validates", "filters", "transforms")
460
+ - Docstring describes particular functionality being tested
461
+ - Assertions only check return types, basic existence, or that no exceptions occurred
462
+ - Missing assertions that would actually verify the claimed behavior
463
+ - Could pass even if the specific behavior is completely broken
464
+
465
+ **Example:**
466
+ ```python
467
+ def test_plot_with_unsorted_bins_list():
468
+ """Test price architecture plot automatically sorts unsorted bins list."""
469
+ df = pd.DataFrame({
470
+ "unit_price": [1, 2, 3],
471
+ "retailer": ["Walmart", "Target", "Amazon"],
472
+ })
473
+
474
+ # BAD: Claims to test sorting but doesn't verify it
475
+ result_ax = price.plot(
476
+ df=df,
477
+ value_col="unit_price",
478
+ group_col="retailer",
479
+ bins=[3, 1, 2], # Unsorted bins - but test doesn't verify they get sorted!
480
+ )
481
+
482
+ assert isinstance(result_ax, Axes) # Only checks return type
483
+
484
+ def test_validates_email_format():
485
+ """Test that email validation properly checks format."""
486
+ validator = EmailValidator()
487
+
488
+ # BAD: Claims to test validation but doesn't verify it
489
+ result = validator.validate("not-an-email")
490
+ assert result is not None # Doesn't check if validation actually worked
491
+
492
+ def test_filters_inactive_customers():
493
+ """Test customer filtering removes inactive customers."""
494
+ customers = create_test_customers() # Mix of active/inactive
495
+
496
+ # BAD: Claims to test filtering but doesn't verify the filtering logic
497
+ filtered = CustomerFilter().filter_active(customers)
498
+ assert len(filtered) >= 0 # Trivial assertion, doesn't verify filtering
499
+
500
+ def test_calculates_price_elasticity():
501
+ """Test price elasticity calculation returns correct values."""
502
+ price_data = [100, 110, 120, 130]
503
+ demand_data = [1000, 900, 800, 700]
504
+
505
+ # BAD: Claims to test calculation but doesn't verify correctness
506
+ elasticity = calculate_elasticity(price_data, demand_data)
507
+ assert elasticity is not None # Doesn't verify the calculation is correct
508
+
509
+ # GOOD: Actually verify the claimed behavior
510
+ def test_plot_with_unsorted_bins_list():
511
+ """Test price architecture plot automatically sorts unsorted bins list."""
512
+ df = pd.DataFrame({
513
+ "unit_price": [1, 2, 3],
514
+ "retailer": ["Walmart", "Target", "Amazon"],
515
+ })
516
+
517
+ result_ax = price.plot(
518
+ df=df,
519
+ value_col="unit_price",
520
+ group_col="retailer",
521
+ bins=[3, 1, 2], # Unsorted bins
522
+ )
523
+
524
+ # GOOD: Verify the bins were actually sorted by checking output
525
+ y_labels = [label.get_text() for label in result_ax.get_yticklabels()]
526
+ assert "$1.0 - $2.0" in y_labels[0] # Sorted order: first bin is 1-2
527
+ assert "$2.0 - $3.0" in y_labels[1] # Second bin is 2-3
528
+
529
+ def test_validates_email_format():
530
+ """Test that email validation properly checks format."""
531
+ validator = EmailValidator()
532
+
533
+ # GOOD: Actually test validation behavior
534
+ assert validator.validate("user@example.com") == True
535
+ assert validator.validate("invalid-email") == False
536
+ assert validator.validate("missing@") == False
537
+
538
+ def test_filters_inactive_customers():
539
+ """Test customer filtering removes inactive customers."""
540
+ active_customers = [Customer(id=1, active=True), Customer(id=2, active=True)]
541
+ inactive_customers = [Customer(id=3, active=False), Customer(id=4, active=False)]
542
+ all_customers = active_customers + inactive_customers
543
+
544
+ # GOOD: Verify filtering actually works
545
+ filtered = CustomerFilter().filter_active(all_customers)
546
+ assert len(filtered) == 2 # Should have exactly 2 active customers
547
+ assert all(c.active for c in filtered) # All should be active
548
+ assert {c.id for c in filtered} == {1, 2} # Should be the right customers
549
+ ```
550
+
551
+ **Why this matters:**
552
+ - Test names and docstrings serve as documentation of what functionality is tested
553
+ - False confidence is dangerous - tests appear to cover behavior but actually don't
554
+ - Bugs in the claimed functionality will go undetected
555
+ - Future developers may assume the behavior is tested and working correctly
556
+ - Makes debugging harder when the "tested" functionality actually fails
557
+
558
+ ## Instructions:
559
+ 1. **View the PR** using `gh pr view $1` and `gh pr diff $1` to understand the changes
560
+ 2. **Optionally checkout the PR** if local examination is needed using `gh pr checkout $1` (this fetches if necessary)
561
+ 3. **Check for Python test files** - if none exist, provide guidance on what should be tested based on the PR changes
562
+ 4. **Identify the OpenRetailScience module under test** by analyzing imports and function calls in the test code
563
+ 5. Review each test function in the provided PR
564
+ 6. Categorize any problematic tests using the categories above (1-11)
565
+ 7. **Highlight the specific problematic code** from each test function
566
+ 8. Provide brief explanations for why each flagged test is problematic
567
+ 9. Suggest improvements where appropriate (e.g., "combine with test_X", "use pytest.parametrize", "add actual package functionality", "use realistic retail/business data")
568
+ 10. **When suggestions involve simple fixes, provide the corrected code**
569
+ 11. Highlight any tests that might be salvageable with minor modifications
570
+
571
+ ## Output Format:
572
+ ```
573
+ ## LANGUAGE: Python
574
+ ## PACKAGE UNDER TEST: openretailscience.[module_name]
575
+
576
+ PROBLEMATIC TESTS IDENTIFIED:
577
+
578
+ ### Test: test_function_name()
579
+
580
+ **Issue**: [Brief description] [Lines affected]
581
+
582
+ Problematic code: ```python
583
+ [highlight the specific problematic code from the test]
584
+ ```
585
+
586
+ **Suggestion**: [How to improve or whether to remove]
587
+
588
+ Code fix: ```python
589
+ [if suggestion includes a simple fix, show the corrected code here]
590
+ ```
591
+
592
+ ## POSITIVE OBSERVATIONS
593
+
594
+ The following tests are well-structured and properly test the package functionality:
595
+
596
+ 1. test_function_name (test code lines) - very brief description of the test
597
+
598
+ SUMMARY:
599
+ - Language: Python
600
+ - Package analyzed: openretailscience.[module_name]
601
+ - Total tests reviewed: [X]
602
+ - Problematic tests found: [X]
603
+
604
+ ## Recommendations
605
+
606
+ [A numbered list of recommendations - if any]
607
+ ```
@@ -0,0 +1,9 @@
1
+ GCP_PROJECT_ID =
2
+
3
+ # Snowflake CI Configuration (for integration tests)
4
+ SNOWFLAKE_CI_ACCOUNT =
5
+ SNOWFLAKE_CI_USER =
6
+ SNOWFLAKE_CI_WAREHOUSE =
7
+ SNOWFLAKE_CI_DATABASE =
8
+ SNOWFLAKE_CI_SCHEMA =
9
+ SNOWFLAKE_CI_PRIVATE_KEY_PATH =
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ Steps to reproduce the behavior:
15
+
16
+ 1. Go to '...'
17
+ 2. Click on '....'
18
+ 3. Scroll down to '....'
19
+ 4. See error
20
+
21
+ **Expected behavior**
22
+ A clear and concise description of what you expected to happen.
23
+
24
+ **Screenshots**
25
+ If applicable, add screenshots to help explain your problem.
26
+
27
+ **Desktop (please complete the following information):**
28
+
29
+ - OS: [e.g. iOS]
30
+ - Python Version: [e.g. 22]
31
+
32
+ **Additional context**
33
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,15 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "uv"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ open-pull-requests-limit: 5
8
+ commit-message:
9
+ prefix: "chore(deps)"
10
+ prefix-development: "chore(deps-dev)"
11
+ groups:
12
+ production-dependencies:
13
+ dependency-type: "production"
14
+ development-dependencies:
15
+ dependency-type: "development"