rangebar 11.6.0__tar.gz → 11.6.1__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 (276) hide show
  1. {rangebar-11.6.0 → rangebar-11.6.1}/.mise.toml +5 -6
  2. {rangebar-11.6.0 → rangebar-11.6.1}/CHANGELOG.md +9 -0
  3. {rangebar-11.6.0 → rangebar-11.6.1}/Cargo.lock +9 -9
  4. {rangebar-11.6.0 → rangebar-11.6.1}/Cargo.toml +2 -2
  5. {rangebar-11.6.0 → rangebar-11.6.1}/PKG-INFO +1 -1
  6. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/resource_guard.py +80 -6
  7. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/publish-to-pypi.sh +37 -30
  8. {rangebar-11.6.0 → rangebar-11.6.1}/.gitignore +0 -0
  9. {rangebar-11.6.0 → rangebar-11.6.1}/.mcp.json +0 -0
  10. {rangebar-11.6.0 → rangebar-11.6.1}/.pre-commit-config.yaml +0 -0
  11. {rangebar-11.6.0 → rangebar-11.6.1}/.releaserc.yml +0 -0
  12. {rangebar-11.6.0 → rangebar-11.6.1}/CLAUDE.md +0 -0
  13. {rangebar-11.6.0 → rangebar-11.6.1}/LICENSE +0 -0
  14. {rangebar-11.6.0 → rangebar-11.6.1}/README.md +0 -0
  15. {rangebar-11.6.0 → rangebar-11.6.1}/RESUME.md +0 -0
  16. {rangebar-11.6.0 → rangebar-11.6.1}/STATISTICAL_VALIDITY_AUDIT.md +0 -0
  17. {rangebar-11.6.0 → rangebar-11.6.1}/benches/rangebar_bench.rs +0 -0
  18. {rangebar-11.6.0 → rangebar-11.6.1}/build.rs +0 -0
  19. {rangebar-11.6.0 → rangebar-11.6.1}/crates/CLAUDE.md +0 -0
  20. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/CHANGELOG.md +0 -0
  21. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/Cargo.toml +0 -0
  22. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/README.md +0 -0
  23. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/arrow_export.rs +0 -0
  24. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/checkpoint.rs +0 -0
  25. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/fixed_point.rs +0 -0
  26. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/interbar.rs +0 -0
  27. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/lib.rs +0 -0
  28. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/processor.rs +0 -0
  29. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/test_data_loader.rs +0 -0
  30. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/test_utils/generators.rs +0 -0
  31. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/test_utils/mod.rs +0 -0
  32. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/timestamp.rs +0 -0
  33. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/src/types.rs +0 -0
  34. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/tests/cross_boundary_validation.rs +0 -0
  35. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/tests/cross_date_real_data_validation.rs +0 -0
  36. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/tests/cross_year_boundary_test.rs +0 -0
  37. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-core/tests/incomplete_bar_continuation_proof.rs +0 -0
  38. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/CHANGELOG.md +0 -0
  39. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/Cargo.toml +0 -0
  40. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/README.md +0 -0
  41. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/binance/checksum.rs +0 -0
  42. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/binance/historical.rs +0 -0
  43. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/binance/mod.rs +0 -0
  44. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/binance/symbols.rs +0 -0
  45. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/binance/websocket.rs +0 -0
  46. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/exness/builder.rs +0 -0
  47. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/exness/client.rs +0 -0
  48. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/exness/conversion.rs +0 -0
  49. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/exness/mod.rs +0 -0
  50. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/exness/types.rs +0 -0
  51. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-providers/src/lib.rs +0 -0
  52. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/CHANGELOG.md +0 -0
  53. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/Cargo.toml +0 -0
  54. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/README.md +0 -0
  55. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/src/indicators.rs +0 -0
  56. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/src/lib.rs +0 -0
  57. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/src/processor.rs +0 -0
  58. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/src/replay_buffer.rs +0 -0
  59. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/src/stats.rs +0 -0
  60. {rangebar-11.6.0 → rangebar-11.6.1}/crates/rangebar-streaming/src/universal.rs +0 -0
  61. {rangebar-11.6.0 → rangebar-11.6.1}/deny.toml +0 -0
  62. {rangebar-11.6.0 → rangebar-11.6.1}/docs/ARCHITECTURE.md +0 -0
  63. {rangebar-11.6.0 → rangebar-11.6.1}/docs/CONTEXT.md +0 -0
  64. {rangebar-11.6.0 → rangebar-11.6.1}/docs/MEMORY_REMEDIATION_PLAN.md +0 -0
  65. {rangebar-11.6.0 → rangebar-11.6.1}/docs/adr/2026-01-31-realtime-streaming-api.md +0 -0
  66. {rangebar-11.6.0 → rangebar-11.6.1}/docs/analysis/2025-10-10-flash-crash.md +0 -0
  67. {rangebar-11.6.0 → rangebar-11.6.1}/docs/api.md +0 -0
  68. {rangebar-11.6.0 → rangebar-11.6.1}/docs/development/PERFORMANCE.md +0 -0
  69. {rangebar-11.6.0 → rangebar-11.6.1}/docs/development/RELEASE.md +0 -0
  70. {rangebar-11.6.0 → rangebar-11.6.1}/docs/migration-v8.md +0 -0
  71. {rangebar-11.6.0 → rangebar-11.6.1}/docs/plans/issue-59-inter-bar-features.md +0 -0
  72. {rangebar-11.6.0 → rangebar-11.6.1}/docs/rangebar_core_api.md +0 -0
  73. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/2026-02-02-intrabar-microstructure-claude-opus.md +0 -0
  74. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/2026-02-02-intrabar-microstructure-gemini-3-pro.md +0 -0
  75. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/INDEX.md +0 -0
  76. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/adversarial-audit-methodology.md +0 -0
  77. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/external/time-to-convergence-stationarity-gap.md +0 -0
  78. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/labeling-for-ml.md +0 -0
  79. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/market-regime-patterns.md +0 -0
  80. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/multi-threshold-patterns.md +0 -0
  81. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/multifactor-patterns.md +0 -0
  82. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/pattern-research-summary.md +0 -0
  83. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/price-action-patterns.md +0 -0
  84. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/tda-parameter-sensitivity-audit.md +0 -0
  85. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/tda-regime-patterns.md +0 -0
  86. {rangebar-11.6.0 → rangebar-11.6.1}/docs/research/volatility-regime-patterns.md +0 -0
  87. {rangebar-11.6.0 → rangebar-11.6.1}/examples/README.md +0 -0
  88. {rangebar-11.6.0 → rangebar-11.6.1}/examples/backtesting_integration.py +0 -0
  89. {rangebar-11.6.0 → rangebar-11.6.1}/examples/basic_usage.py +0 -0
  90. {rangebar-11.6.0 → rangebar-11.6.1}/examples/binance_csv_example.py +0 -0
  91. {rangebar-11.6.0 → rangebar-11.6.1}/examples/get_range_bars_example.py +0 -0
  92. {rangebar-11.6.0 → rangebar-11.6.1}/examples/validate_output.py +0 -0
  93. {rangebar-11.6.0 → rangebar-11.6.1}/examples/with_clickhouse_cache.py +0 -0
  94. {rangebar-11.6.0 → rangebar-11.6.1}/package-lock.json +0 -0
  95. {rangebar-11.6.0 → rangebar-11.6.1}/package.json +0 -0
  96. {rangebar-11.6.0 → rangebar-11.6.1}/pyproject.toml +0 -0
  97. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/CLAUDE.md +0 -0
  98. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/__init__.py +0 -0
  99. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/__init__.pyi +0 -0
  100. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/checkpoint.py +0 -0
  101. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/cli.py +0 -0
  102. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/CLAUDE.md +0 -0
  103. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/__init__.py +0 -0
  104. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/bulk_operations.py +0 -0
  105. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/cache.py +0 -0
  106. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/client.py +0 -0
  107. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/config.py +0 -0
  108. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/mixin.py +0 -0
  109. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/preflight.py +0 -0
  110. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/query_operations.py +0 -0
  111. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/schema.sql +0 -0
  112. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/clickhouse/tunnel.py +0 -0
  113. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/constants.py +0 -0
  114. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/conversion.py +0 -0
  115. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/exceptions.py +0 -0
  116. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/exness.py +0 -0
  117. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/hooks.py +0 -0
  118. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/logging.py +0 -0
  119. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/notify/__init__.py +0 -0
  120. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/notify/pushover.py +0 -0
  121. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/notify/telegram.py +0 -0
  122. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/orchestration/__init__.py +0 -0
  123. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/orchestration/count_bounded.py +0 -0
  124. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/orchestration/helpers.py +0 -0
  125. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/orchestration/models.py +0 -0
  126. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/orchestration/precompute.py +0 -0
  127. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/orchestration/range_bars.py +0 -0
  128. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/orchestration/tick_fetcher.py +0 -0
  129. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/ouroboros.py +0 -0
  130. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/processors/__init__.py +0 -0
  131. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/processors/api.py +0 -0
  132. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/processors/core.py +0 -0
  133. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/storage/__init__.py +0 -0
  134. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/storage/checksum_registry.py +0 -0
  135. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/storage/parquet.py +0 -0
  136. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/streaming.py +0 -0
  137. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/validation/__init__.py +0 -0
  138. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/validation/cache_staleness.py +0 -0
  139. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/validation/continuity.py +0 -0
  140. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/validation/gap_classification.py +0 -0
  141. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/validation/post_storage.py +0 -0
  142. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/validation/tier1.py +0 -0
  143. {rangebar-11.6.0 → rangebar-11.6.1}/python/rangebar/validation/tier2.py +0 -0
  144. {rangebar-11.6.0 → rangebar-11.6.1}/rust-toolchain.toml +0 -0
  145. {rangebar-11.6.0 → rangebar-11.6.1}/rustfmt.toml +0 -0
  146. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/adwin_regime_detection_polars.py +0 -0
  147. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/analyze_flash_crash.py +0 -0
  148. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/bootstrap_permutation_validation_polars.py +0 -0
  149. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/build-release.sh +0 -0
  150. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/cache_clear.py +0 -0
  151. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/cache_status.py +0 -0
  152. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/check-release-config.sh +0 -0
  153. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/coarse_to_fine_cascade.py +0 -0
  154. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/combined_pattern_audit_polars.py +0 -0
  155. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/combined_regime_analysis_polars.py +0 -0
  156. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/combined_rv_alignment_analysis_polars.py +0 -0
  157. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/cross_asset_correlation_polars.py +0 -0
  158. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/cross_regime_correlation_polars.py +0 -0
  159. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/cross_threshold_alignment.py +0 -0
  160. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/dependency_monitor.sh +0 -0
  161. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/direction_patterns_reaudit.py +0 -0
  162. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/download_exness_eurusd.py +0 -0
  163. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/download_exness_forex.py +0 -0
  164. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/duration_autocorrelation.py +0 -0
  165. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/duration_autocorrelation_audit.py +0 -0
  166. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/duration_volatility_prediction.py +0 -0
  167. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/fdr_corrected_patterns.py +0 -0
  168. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/fill_all_symbols.py +0 -0
  169. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/fill_gaps_2025_2026.py +0 -0
  170. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/fill_gaps_littleblack.py +0 -0
  171. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/fill_gaps_retry.py +0 -0
  172. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/historical_formation_patterns_polars.py +0 -0
  173. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/historical_formation_regime_polars.py +0 -0
  174. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/hurst_adjusted_kelly_polars.py +0 -0
  175. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/hurst_adjusted_psr_analysis_polars.py +0 -0
  176. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/hurst_exponent_analysis_polars.py +0 -0
  177. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/hurst_multi_estimator_audit.py +0 -0
  178. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/microstructure_clickhouse.py +0 -0
  179. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/microstructure_patterns.py +0 -0
  180. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/microstructure_simple.py +0 -0
  181. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/monitor_population.py +0 -0
  182. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/multi_threshold_pattern_analysis_polars.py +0 -0
  183. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/multibar_continuation.py +0 -0
  184. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/multibar_forward_returns_polars.py +0 -0
  185. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/multifactor_multigranularity_patterns.py +0 -0
  186. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/multifactor_patterns.py +0 -0
  187. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/multifactor_patterns_polars.py +0 -0
  188. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/multithreshold_combinations_polars.py +0 -0
  189. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/multithreshold_regime_combinations_polars.py +0 -0
  190. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/oos_validation_polars.py +0 -0
  191. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/parameter_sensitivity_polars.py +0 -0
  192. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/pattern_correlation_analysis_polars.py +0 -0
  193. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/pattern_return_profiles_polars.py +0 -0
  194. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/pattern_return_stats.py +0 -0
  195. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/populate_1000dbps.py +0 -0
  196. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/populate_250dbps.py +0 -0
  197. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/populate_250dbps_extended.py +0 -0
  198. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/populate_safe.py +0 -0
  199. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/position_sizing_analysis_polars.py +0 -0
  200. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/process_exness_eurusd_to_cache.py +0 -0
  201. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/profiling_tools.sh +0 -0
  202. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/psr_mintrl_analysis_polars.py +0 -0
  203. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/publish-wheels.sh +0 -0
  204. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/regenerate_cache.py +0 -0
  205. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/regime_analysis.py +0 -0
  206. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/regime_analysis_50dbps_polars.py +0 -0
  207. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/regime_analysis_polars.py +0 -0
  208. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/regime_transition_analysis_polars.py +0 -0
  209. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/run_large_scale_benchmark.sh +0 -0
  210. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/run_length_momentum_analysis.py +0 -0
  211. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/run_length_momentum_multi_symbol.py +0 -0
  212. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/run_length_momentum_wfo.py +0 -0
  213. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/rv_return_profile_analysis_polars.py +0 -0
  214. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/semantic-release.sh +0 -0
  215. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_break_event_alignment_polars.py +0 -0
  216. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_conditioned_patterns.py +0 -0
  217. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_cupy_accelerated.py +0 -0
  218. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_gpu_analysis.py +0 -0
  219. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_hurst_by_regime_polars.py +0 -0
  220. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_parameter_sweep_audit.py +0 -0
  221. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_regime_hurst_analysis_polars.py +0 -0
  222. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_regime_pattern_analysis_polars.py +0 -0
  223. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_ripser_plusplus.py +0 -0
  224. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_rolling_threshold.py +0 -0
  225. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_solusdt_250_audit.py +0 -0
  226. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_solusdt_250_littleblack.py +0 -0
  227. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_structural_break_analysis_polars.py +0 -0
  228. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_volatility_forecast.py +0 -0
  229. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_wfo_3way.py +0 -0
  230. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_wfo_abstain.py +0 -0
  231. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/tda_wfo_audit.py +0 -0
  232. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/temporal_safe_patterns_polars.py +0 -0
  233. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/three_bar_alignment_analysis_polars.py +0 -0
  234. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/three_bar_pattern_analysis_polars.py +0 -0
  235. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/three_bar_pattern_audit_polars.py +0 -0
  236. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/three_factor_hurst_analysis_polars.py +0 -0
  237. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/three_factor_pattern_analysis_polars.py +0 -0
  238. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/transaction_cost_analysis_polars.py +0 -0
  239. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/trend_filter_analysis.py +0 -0
  240. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/upload_eurusd_to_clickhouse.py +0 -0
  241. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/validate_clickhouse.py +0 -0
  242. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/validate_memory_efficiency.py +0 -0
  243. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/validate_microstructure_features.py +0 -0
  244. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/validate_n_range_bars.py +0 -0
  245. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/volatility_regime_analysis_polars.py +0 -0
  246. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/volatility_regime_audit_polars.py +0 -0
  247. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/volume_conditioned_patterns.py +0 -0
  248. {rangebar-11.6.0 → rangebar-11.6.1}/scripts/volume_conditioned_patterns_polars.py +0 -0
  249. {rangebar-11.6.0 → rangebar-11.6.1}/src/lib.rs +0 -0
  250. {rangebar-11.6.0 → rangebar-11.6.1}/test_data/BTCUSDT/BTCUSDT_aggTrades_20250901.csv +0 -0
  251. {rangebar-11.6.0 → rangebar-11.6.1}/test_data/ETHUSDT/ETHUSDT_aggTrades_20250901.csv +0 -0
  252. {rangebar-11.6.0 → rangebar-11.6.1}/test_data/README.md +0 -0
  253. {rangebar-11.6.0 → rangebar-11.6.1}/tests/conftest.py +0 -0
  254. {rangebar-11.6.0 → rangebar-11.6.1}/tests/fixtures/.gitignore +0 -0
  255. {rangebar-11.6.0 → rangebar-11.6.1}/tests/fixtures/BTCUSDT-aggTrades-2024-01-01.zip +0 -0
  256. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_cache_schema_evolution.py +0 -0
  257. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_clickhouse.py +0 -0
  258. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_clickhouse_integration.py +0 -0
  259. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_e2e_optimized.py +0 -0
  260. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_edge_cases.py +0 -0
  261. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_examples.py +0 -0
  262. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_get_n_range_bars.py +0 -0
  263. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_get_range_bars_e2e.py +0 -0
  264. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_issue_5_reproduction.py +0 -0
  265. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_issues_7_8.py +0 -0
  266. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_microstructure_features.py +0 -0
  267. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_ouroboros.py +0 -0
  268. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_polars_only_downstream.py +0 -0
  269. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_preflight.py +0 -0
  270. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_python_api.py +0 -0
  271. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_real_data.py +0 -0
  272. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_rust_bindings.py +0 -0
  273. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_storage.py +0 -0
  274. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_streaming.py +0 -0
  275. {rangebar-11.6.0 → rangebar-11.6.1}/tests/test_validation_presets.py +0 -0
  276. {rangebar-11.6.0 → rangebar-11.6.1}/uv.lock +0 -0
@@ -17,12 +17,11 @@ GH_TOKEN = "{{ read_file(path=env.HOME ~ '/.claude/.secrets/gh-token-terrylica')
17
17
  GITHUB_TOKEN = "{{ read_file(path=env.HOME ~ '/.claude/.secrets/gh-token-terrylica') | trim }}"
18
18
 
19
19
  # =============================================================================
20
- # Doppler Configuration (SSoT for secrets)
20
+ # 1Password Configuration (SSoT for secrets)
21
21
  # =============================================================================
22
- # PyPI: doppler secrets get PYPI_TOKEN --project claude-config --config prd
23
- # GitHub PAT: doppler secrets get GH_TOKEN_TERRYLICA --project main --config dev
24
- DOPPLER_PYPI_PROJECT = "claude-config"
25
- DOPPLER_PYPI_CONFIG = "prd"
22
+ # PyPI: op item get djevteztvbcqgcm3yl4njkawjq --fields credential --reveal
23
+ # GitHub PAT: stored in gh-token-terrylica file
24
+ OP_PYPI_ITEM = "djevteztvbcqgcm3yl4njkawjq"
26
25
 
27
26
  # =============================================================================
28
27
  # ClickHouse Cache Configuration (SSoT for cache hosts)
@@ -435,7 +434,7 @@ description = "Preview what semantic-release would do (no changes)"
435
434
  run = "bun install --silent 2>/dev/null && GH_CONFIG_DIR=$HOME/.config/gh/profiles/terrylica GITHUB_TOKEN=$(gh auth token) bun run semantic-release --dry-run --no-ci"
436
435
 
437
436
  [tasks."release:pypi"]
438
- description = "Publish to PyPI using Doppler credentials (local-only, ADR-0027)"
437
+ description = "Publish to PyPI using 1Password credentials (local-only, ADR-0027)"
439
438
  depends = ["release:build-all"]
440
439
  run = "./scripts/publish-to-pypi.sh"
441
440
 
@@ -1,3 +1,12 @@
1
+ ## [11.6.1](https://github.com/terrylica/rangebar-py/compare/v11.6.0...v11.6.1) (2026-02-02)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **ci:** correct rust-toolchain action name ([fa252ce](https://github.com/terrylica/rangebar-py/commit/fa252ceeb1b2f3d4216fceb3e0eaf3fbdc4bed6a))
7
+ * **ci:** simplify workflow to match working configuration ([5128fd6](https://github.com/terrylica/rangebar-py/commit/5128fd6a5ade367dbde371c186de0512095c0116))
8
+ * **resource:** make auto_memory_guard() multiprocessing-safe (Issue [#61](https://github.com/terrylica/rangebar-py/issues/61)) ([b55057a](https://github.com/terrylica/rangebar-py/commit/b55057afb3a10f530ec8d1ac1520d81169ad5fcc))
9
+
1
10
  # [11.6.0](https://github.com/terrylica/rangebar-py/compare/v11.5.0...v11.6.0) (2026-02-02)
2
11
 
3
12
 
@@ -3430,7 +3430,7 @@ dependencies = [
3430
3430
 
3431
3431
  [[package]]
3432
3432
  name = "rangebar"
3433
- version = "11.6.0"
3433
+ version = "11.6.1"
3434
3434
  dependencies = [
3435
3435
  "chrono",
3436
3436
  "insta",
@@ -3452,7 +3452,7 @@ dependencies = [
3452
3452
 
3453
3453
  [[package]]
3454
3454
  name = "rangebar-batch"
3455
- version = "11.6.0"
3455
+ version = "11.6.1"
3456
3456
  dependencies = [
3457
3457
  "polars",
3458
3458
  "rangebar-core",
@@ -3464,7 +3464,7 @@ dependencies = [
3464
3464
 
3465
3465
  [[package]]
3466
3466
  name = "rangebar-cli"
3467
- version = "11.6.0"
3467
+ version = "11.6.1"
3468
3468
  dependencies = [
3469
3469
  "chrono",
3470
3470
  "clap",
@@ -3489,7 +3489,7 @@ dependencies = [
3489
3489
 
3490
3490
  [[package]]
3491
3491
  name = "rangebar-config"
3492
- version = "11.6.0"
3492
+ version = "11.6.1"
3493
3493
  dependencies = [
3494
3494
  "chrono",
3495
3495
  "config",
@@ -3501,7 +3501,7 @@ dependencies = [
3501
3501
 
3502
3502
  [[package]]
3503
3503
  name = "rangebar-core"
3504
- version = "11.6.0"
3504
+ version = "11.6.1"
3505
3505
  dependencies = [
3506
3506
  "ahash",
3507
3507
  "arrow",
@@ -3518,7 +3518,7 @@ dependencies = [
3518
3518
 
3519
3519
  [[package]]
3520
3520
  name = "rangebar-io"
3521
- version = "11.6.0"
3521
+ version = "11.6.1"
3522
3522
  dependencies = [
3523
3523
  "polars",
3524
3524
  "rangebar-core",
@@ -3528,7 +3528,7 @@ dependencies = [
3528
3528
 
3529
3529
  [[package]]
3530
3530
  name = "rangebar-providers"
3531
- version = "11.6.0"
3531
+ version = "11.6.1"
3532
3532
  dependencies = [
3533
3533
  "chrono",
3534
3534
  "csv",
@@ -3548,7 +3548,7 @@ dependencies = [
3548
3548
 
3549
3549
  [[package]]
3550
3550
  name = "rangebar-py"
3551
- version = "11.6.0"
3551
+ version = "11.6.1"
3552
3552
  dependencies = [
3553
3553
  "arrow",
3554
3554
  "arrow-array",
@@ -3567,7 +3567,7 @@ dependencies = [
3567
3567
 
3568
3568
  [[package]]
3569
3569
  name = "rangebar-streaming"
3570
- version = "11.6.0"
3570
+ version = "11.6.1"
3571
3571
  dependencies = [
3572
3572
  "async-trait",
3573
3573
  "chrono",
@@ -10,7 +10,7 @@ resolver = "2"
10
10
  [workspace.package]
11
11
  # CRITICAL: Prevent crates.io publishing - this is a PyPI-only project
12
12
  publish = false
13
- version = "11.6.0"
13
+ version = "11.6.1"
14
14
  authors = ["Terry Li <terry@eonlabs.com>"]
15
15
  categories = ["algorithms", "data-structures", "finance"]
16
16
  documentation = "https://docs.rs/rangebar"
@@ -97,7 +97,7 @@ criterion = { version = "0.5", features = ["html_reports"] }
97
97
 
98
98
  [package]
99
99
  name = "rangebar-py"
100
- version = "11.6.0"
100
+ version = "11.6.1"
101
101
  edition = "2021"
102
102
  authors = ["Terry Li"]
103
103
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rangebar
3
- Version: 11.6.0
3
+ Version: 11.6.1
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Financial and Insurance Industry
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -6,6 +6,7 @@ using only stdlib modules (no psutil dependency).
6
6
  MEM-009: Process-level RLIMIT_AS cap (MemoryError instead of OOM kill)
7
7
  MEM-010: Pre-flight memory estimation before tick loading
8
8
  MEM-011: Environment variable default (RANGEBAR_MAX_MEMORY_GB)
9
+ MEM-012: Multiprocessing-safe memory guard (Issue #61)
9
10
 
10
11
  Environment Variables
11
12
  ---------------------
@@ -18,7 +19,23 @@ RANGEBAR_MAX_MEMORY_PCT : float
18
19
  Default memory limit as fraction of total RAM (0.0-1.0).
19
20
  Example: RANGEBAR_MAX_MEMORY_PCT=0.7 (for 70% of RAM)
20
21
 
21
- If both are set, the smaller limit is used.
22
+ RANGEBAR_NO_MEMORY_GUARD : str
23
+ Set to "1" to disable automatic memory guard entirely.
24
+ Useful for multiprocessing workers or when RLIMIT_AS conflicts
25
+ with Polars/Rust memory allocators.
26
+
27
+ If both GB and PCT are set, the smaller limit is used.
28
+
29
+ Multiprocessing Safety (Issue #61)
30
+ ----------------------------------
31
+ On Linux, RLIMIT_AS (virtual address space) conflicts with mmap-based
32
+ allocators used by Polars and Rust. This can cause "Cannot allocate memory"
33
+ errors even when physical RAM is available.
34
+
35
+ The auto_memory_guard() function:
36
+ 1. Skips if RANGEBAR_NO_MEMORY_GUARD=1
37
+ 2. Skips if running in a multiprocessing child (detected via _RANGEBAR_GUARD_PID)
38
+ 3. On Linux, uses RLIMIT_DATA instead of RLIMIT_AS to avoid mmap conflicts
22
39
  """
23
40
 
24
41
  from __future__ import annotations
@@ -120,6 +137,7 @@ def set_memory_limit(
120
137
  limit_bytes = min(limits)
121
138
 
122
139
  # MEM-009: Set process-level cap
140
+ # MEM-012: Use RLIMIT_DATA on Linux to avoid mmap conflicts (Issue #61)
123
141
  try:
124
142
  if sys.platform == "darwin":
125
143
  # macOS: RLIMIT_RSS is advisory (kernel doesn't enforce)
@@ -130,11 +148,19 @@ def set_memory_limit(
130
148
  limit_bytes = hard_limit
131
149
  resource.setrlimit(resource.RLIMIT_RSS, (limit_bytes, limit_bytes))
132
150
  else:
133
- # Linux: RLIMIT_AS is enforced by kernel
134
- _, hard_limit = resource.getrlimit(resource.RLIMIT_AS)
151
+ # Linux: Use RLIMIT_DATA instead of RLIMIT_AS (Issue #61)
152
+ # RLIMIT_AS limits virtual address space including mmap regions,
153
+ # which conflicts with Polars/Rust allocators that use mmap().
154
+ # RLIMIT_DATA limits the data segment (heap) which is more
155
+ # appropriate for controlling actual memory allocation.
156
+ #
157
+ # Note: RLIMIT_DATA is less strict than RLIMIT_AS - it won't
158
+ # prevent mmap allocations, but it will limit malloc/brk usage.
159
+ # For full protection, users should rely on cgroups or systemd.
160
+ _, hard_limit = resource.getrlimit(resource.RLIMIT_DATA)
135
161
  if hard_limit != resource.RLIM_INFINITY and limit_bytes > hard_limit:
136
162
  limit_bytes = hard_limit
137
- resource.setrlimit(resource.RLIMIT_AS, (limit_bytes, limit_bytes))
163
+ resource.setrlimit(resource.RLIMIT_DATA, (limit_bytes, limit_bytes))
138
164
  except (ValueError, OSError):
139
165
  # Can't set limit (e.g., unprivileged user, macOS restrictions)
140
166
  return -1
@@ -149,6 +175,10 @@ def set_memory_limit(
149
175
  # Mutable container to track if memory limit was applied (avoids global stmt)
150
176
  _memory_limit_state: dict[str, bool] = {"applied": False}
151
177
 
178
+ # MEM-012: Environment variable key for multiprocessing-safe state tracking
179
+ # This survives fork() and allows child processes to detect parent's limit
180
+ _GUARD_PID_KEY = "_RANGEBAR_GUARD_PID"
181
+
152
182
 
153
183
  def _parse_env_float(name: str) -> float | None:
154
184
  """Parse environment variable as float, returning None on failure."""
@@ -245,13 +275,42 @@ def ensure_memory_limit(
245
275
  return limit
246
276
 
247
277
 
278
+ def _is_multiprocessing_child() -> bool:
279
+ """Check if we're in a multiprocessing child process (MEM-012).
280
+
281
+ Detects if memory guard was already applied by a parent process
282
+ by checking the _RANGEBAR_GUARD_PID environment variable.
283
+
284
+ Returns True if:
285
+ 1. _RANGEBAR_GUARD_PID is set (parent applied the guard)
286
+ 2. Current PID differs from stored PID (we're a child)
287
+ """
288
+ guard_pid = os.environ.get(_GUARD_PID_KEY)
289
+ if not guard_pid:
290
+ return False
291
+
292
+ try:
293
+ parent_pid = int(guard_pid)
294
+ # If our PID differs from the stored PID, we're a child
295
+ # The child inherits the RLIMIT from parent, no need to re-apply
296
+ return os.getpid() != parent_pid
297
+ except ValueError:
298
+ return False
299
+
300
+
248
301
  def auto_memory_guard() -> int:
249
- """Automatically enable memory guard at module import (MEM-011).
302
+ """Automatically enable memory guard at module import (MEM-011, MEM-012).
250
303
 
251
304
  This function is called when `import rangebar` is executed.
252
305
  It ensures a memory limit is always set unless explicitly disabled
253
306
  via RANGEBAR_NO_MEMORY_GUARD=1.
254
307
 
308
+ Multiprocessing Safety (Issue #61)
309
+ ----------------------------------
310
+ - Skips if RANGEBAR_NO_MEMORY_GUARD=1
311
+ - Skips if running in a multiprocessing child (limit inherited from parent)
312
+ - On Linux, uses RLIMIT_DATA instead of RLIMIT_AS to avoid mmap conflicts
313
+
255
314
  Returns
256
315
  -------
257
316
  int
@@ -266,9 +325,24 @@ def auto_memory_guard() -> int:
266
325
  RANGEBAR_MAX_MEMORY_PCT : float
267
326
  Override default limit as fraction of RAM.
268
327
  """
328
+ # Check explicit disable first
269
329
  if os.environ.get("RANGEBAR_NO_MEMORY_GUARD") == "1":
270
330
  return -1
271
- return ensure_memory_limit()
331
+
332
+ # MEM-012: Skip in multiprocessing children (Issue #61)
333
+ # Child processes inherit RLIMIT from parent via fork()
334
+ if _is_multiprocessing_child():
335
+ _memory_limit_state["applied"] = True # Mark as handled
336
+ return -1
337
+
338
+ # Apply the limit
339
+ limit = ensure_memory_limit()
340
+
341
+ # MEM-012: Store our PID so child processes can detect inheritance
342
+ if limit > 0:
343
+ os.environ[_GUARD_PID_KEY] = str(os.getpid())
344
+
345
+ return limit
272
346
 
273
347
 
274
348
  @dataclass(frozen=True)
@@ -1,13 +1,13 @@
1
1
  #!/bin/bash
2
- # PyPI Publishing with Doppler Secret Management (Local-Only)
2
+ # PyPI Publishing with 1Password Secret Management (Local-Only)
3
3
  #
4
4
  # WORKSPACE-WIDE POLICY: This script must ONLY run on local machines.
5
5
  # CI/CD publishing is forbidden - see ADR-0027 for rationale.
6
6
  #
7
7
  # Prerequisites:
8
- # - Doppler CLI installed (brew install dopplerhq/cli/doppler)
8
+ # - 1Password CLI installed (brew install 1password-cli)
9
9
  # - uv package manager installed (curl -LsSf https://astral.sh/uv/install.sh | sh)
10
- # - PYPI_TOKEN stored in Doppler (project: claude-config, config: prd)
10
+ # - PyPI token stored in 1Password (item: djevteztvbcqgcm3yl4njkawjq)
11
11
  # - pyproject.toml with name and version fields
12
12
  #
13
13
  # Usage:
@@ -20,13 +20,10 @@
20
20
  set -euo pipefail
21
21
 
22
22
  # ============================================================================
23
- # CONFIGURATION (ADR: 2025-12-08-mise-env-centralized-config)
23
+ # CONFIGURATION
24
24
  # ============================================================================
25
- # Environment variables with defaults for backward compatibility.
26
- # These can be pre-set via mise [env] or exported manually.
27
- DOPPLER_PROJECT="${DOPPLER_PROJECT:-claude-config}"
28
- DOPPLER_CONFIG="${DOPPLER_CONFIG:-prd}"
29
- DOPPLER_PYPI_SECRET="${DOPPLER_PYPI_SECRET:-PYPI_TOKEN}"
25
+ # 1Password item ID for PyPI token (project-scoped for rangebar)
26
+ OP_PYPI_ITEM="${OP_PYPI_ITEM:-djevteztvbcqgcm3yl4njkawjq}"
30
27
  PYPI_VERIFY_DELAY="${PYPI_VERIFY_DELAY:-3}"
31
28
 
32
29
  # ============================================================================
@@ -217,26 +214,26 @@ echo ""
217
214
  echo "Publishing to PyPI (Local Workflow)"
218
215
  echo "======================================================"
219
216
 
220
- # Step 0: Verify Doppler token is available
221
- echo -e "\n Step 0: Verifying Doppler credentials..."
217
+ # Step 0: Verify 1Password token is available
218
+ echo -e "\n Step 0: Verifying 1Password credentials..."
222
219
 
223
- if ! command -v doppler &> /dev/null; then
224
- echo " ERROR: Doppler CLI not installed"
225
- echo " Install: brew install dopplerhq/cli/doppler"
220
+ if ! command -v op &> /dev/null; then
221
+ echo " ERROR: 1Password CLI not installed"
222
+ echo " Install: brew install 1password-cli"
226
223
  exit 1
227
224
  fi
228
225
 
229
- # Try to get PYPI_TOKEN from Doppler (configurable via env vars)
230
- if ! PYPI_TOKEN=$(doppler secrets get "$DOPPLER_PYPI_SECRET" --project "$DOPPLER_PROJECT" --config "$DOPPLER_CONFIG" --plain 2>/dev/null); then
231
- echo " ERROR: $DOPPLER_PYPI_SECRET not found in Doppler"
226
+ # Try to get PyPI token from 1Password
227
+ if ! PYPI_TOKEN=$(op item get "$OP_PYPI_ITEM" --fields credential --reveal 2>/dev/null); then
228
+ echo " ERROR: PyPI token not found in 1Password (item: $OP_PYPI_ITEM)"
232
229
  echo ""
233
- echo " To fix, run:"
234
- echo " doppler secrets set $DOPPLER_PYPI_SECRET='your-token' --project $DOPPLER_PROJECT --config $DOPPLER_CONFIG"
230
+ echo " To fix, create a PyPI token and save to 1Password:"
231
+ echo " 1. Get token from: https://pypi.org/manage/account/token/"
232
+ echo " 2. Save to 1Password with: op item create --category='API Credential' --title='PyPI Token' 'credential=pypi-xxx'"
235
233
  echo ""
236
- echo " Get token from: https://pypi.org/manage/account/token/"
237
234
  exit 1
238
235
  fi
239
- echo " Doppler token verified"
236
+ echo " 1Password token verified"
240
237
 
241
238
  # Step 1: Verify pyproject.toml exists
242
239
  echo -e "\n Step 1: Reading package info from pyproject.toml..."
@@ -309,18 +306,28 @@ else
309
306
  echo " Built: dist/${PACKAGE_NAME}-${CURRENT_VERSION}*"
310
307
  fi
311
308
 
312
- # Step 4: Publish to PyPI using Doppler token
313
- echo -e "\n Step 4: Publishing to PyPI..."
314
- echo " Using $DOPPLER_PYPI_SECRET from Doppler ($DOPPLER_PROJECT/$DOPPLER_CONFIG)"
315
-
316
- # Use UV_PUBLISH_TOKEN environment variable for security (no token in process list)
317
- UV_PUBLISH_TOKEN="${PYPI_TOKEN}" $UV_CMD publish 2>&1 | grep -E "(Uploading|succeeded|Failed)" || \
318
- UV_PUBLISH_TOKEN="${PYPI_TOKEN}" $UV_CMD publish
309
+ # Step 3: Publish to PyPI using twine (more reliable for maturin projects)
310
+ echo -e "\n Step 3: Publishing to PyPI..."
311
+ echo " Using PyPI token from 1Password"
312
+
313
+ # Use twine for maturin projects (uv publish has issues with pre-built wheels)
314
+ if grep -q '\[tool.maturin\]' pyproject.toml; then
315
+ # Publish all wheels and sdist for current version
316
+ TWINE_USERNAME=__token__ TWINE_PASSWORD="${PYPI_TOKEN}" twine upload \
317
+ "dist/${PACKAGE_NAME}-${CURRENT_VERSION}"-*.whl \
318
+ "target/wheels/${PACKAGE_NAME}-${CURRENT_VERSION}.tar.gz" 2>&1 || \
319
+ TWINE_USERNAME=__token__ TWINE_PASSWORD="${PYPI_TOKEN}" twine upload \
320
+ "dist/${PACKAGE_NAME}-${CURRENT_VERSION}"-*.whl
321
+ else
322
+ # Use UV_PUBLISH_TOKEN environment variable for security (no token in process list)
323
+ UV_PUBLISH_TOKEN="${PYPI_TOKEN}" $UV_CMD publish 2>&1 | grep -E "(Uploading|succeeded|Failed)" || \
324
+ UV_PUBLISH_TOKEN="${PYPI_TOKEN}" $UV_CMD publish
325
+ fi
319
326
 
320
327
  echo " Published to PyPI"
321
328
 
322
- # Step 5: Verify publication on PyPI
323
- echo -e "\n Step 5: Verifying on PyPI..."
329
+ # Step 4: Verify publication on PyPI
330
+ echo -e "\n Step 4: Verifying on PyPI..."
324
331
  sleep "$PYPI_VERIFY_DELAY"
325
332
 
326
333
  # Check if package version is live on PyPI
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes