mcli-framework 7.9.1__tar.gz → 7.9.5__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.

Potentially problematic release.


This version of mcli-framework might be problematic. Click here for more details.

Files changed (341) hide show
  1. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/PKG-INFO +1 -1
  2. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/pyproject.toml +1 -1
  3. mcli_framework-7.9.5/src/mcli/workflow/doc_convert.py +666 -0
  4. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli_framework.egg-info/PKG-INFO +1 -1
  5. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli_framework.egg-info/SOURCES.txt +2 -0
  6. mcli_framework-7.9.5/tests/unit/test_doc_convert_workflow.py +290 -0
  7. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/dependabot.yml +0 -0
  8. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/workflows/build.yml +0 -0
  9. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/workflows/ci.yml +0 -0
  10. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/workflows/ml-pipeline.yml +0 -0
  11. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/workflows/publish-self-hosted.yml +0 -0
  12. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/workflows/publish.yml +0 -0
  13. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/workflows/release.yml +0 -0
  14. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/workflows/security.yml +0 -0
  15. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/.github/workflows/test.yml +0 -0
  16. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/LICENSE +0 -0
  17. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/MANIFEST.in +0 -0
  18. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/README.md +0 -0
  19. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/mcli_rust/Cargo.toml +0 -0
  20. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/mcli_rust/src/command_parser.rs +0 -0
  21. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/mcli_rust/src/file_watcher.rs +0 -0
  22. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/mcli_rust/src/lib.rs +0 -0
  23. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/mcli_rust/src/process_manager.rs +0 -0
  24. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/mcli_rust/src/tfidf.rs +0 -0
  25. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/setup.cfg +0 -0
  26. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/app/commands_cmd.py +0 -0
  27. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/app/completion_helpers.py +0 -0
  28. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/app/main.py +0 -0
  29. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/app/model/model.py +0 -0
  30. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/app/model_cmd.py +0 -0
  31. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/app/video/video.py +0 -0
  32. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/chat/chat.py +0 -0
  33. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/chat/command_rag.py +0 -0
  34. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/chat/enhanced_chat.py +0 -0
  35. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/chat/system_controller.py +0 -0
  36. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/chat/system_integration.py +0 -0
  37. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/cli.py +0 -0
  38. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/config.toml +0 -0
  39. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/api/api.py +0 -0
  40. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/api/daemon_client.py +0 -0
  41. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/api/daemon_client_local.py +0 -0
  42. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/api/daemon_decorator.py +0 -0
  43. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/api/mcli_decorators.py +0 -0
  44. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/auth.py +0 -0
  45. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/aws_manager.py +0 -0
  46. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/azure_manager.py +0 -0
  47. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/credential_manager.py +0 -0
  48. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/gcp_manager.py +0 -0
  49. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/key_manager.py +0 -0
  50. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/mcli_manager.py +0 -0
  51. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/token_manager.py +0 -0
  52. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/auth/token_util.py +0 -0
  53. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/config/config.py +0 -0
  54. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/custom_commands.py +0 -0
  55. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/discovery/__init__.py +0 -0
  56. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/discovery/command_discovery.py +0 -0
  57. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/erd/erd.py +0 -0
  58. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/erd/generate_graph.py +0 -0
  59. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/files/files.py +0 -0
  60. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/fs/fs.py +0 -0
  61. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/lib.py +0 -0
  62. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/logger/logger.py +0 -0
  63. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/paths.py +0 -0
  64. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/performance/optimizer.py +0 -0
  65. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/performance/rust_bridge.py +0 -0
  66. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/performance/uvloop_config.py +0 -0
  67. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/pickles/pickles.py +0 -0
  68. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/search/cached_vectorizer.py +0 -0
  69. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/secrets/commands.py +0 -0
  70. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/secrets/manager.py +0 -0
  71. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/secrets/repl.py +0 -0
  72. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/secrets/store.py +0 -0
  73. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/services/data_pipeline.py +0 -0
  74. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/services/lsh_client.py +0 -0
  75. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/services/redis_service.py +0 -0
  76. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/shell/shell.py +0 -0
  77. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/toml/toml.py +0 -0
  78. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/ui/styling.py +0 -0
  79. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/ui/visual_effects.py +0 -0
  80. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/lib/watcher/watcher.py +0 -0
  81. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/app.py +0 -0
  82. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/middleware.py +0 -0
  83. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/admin_router.py +0 -0
  84. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/auth_router.py +0 -0
  85. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/backtest_router.py +0 -0
  86. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/data_router.py +0 -0
  87. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/model_router.py +0 -0
  88. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/monitoring_router.py +0 -0
  89. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/portfolio_router.py +0 -0
  90. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/prediction_router.py +0 -0
  91. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/trade_router.py +0 -0
  92. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/routers/websocket_router.py +0 -0
  93. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/api/schemas.py +0 -0
  94. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/auth/auth_manager.py +0 -0
  95. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/auth/models.py +0 -0
  96. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/auth/permissions.py +0 -0
  97. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/backtesting/backtest_engine.py +0 -0
  98. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/backtesting/performance_metrics.py +0 -0
  99. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/backtesting/run.py +0 -0
  100. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/cache.py +0 -0
  101. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/cli/main.py +0 -0
  102. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/config/settings.py +0 -0
  103. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/configs/dvc_config.py +0 -0
  104. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/configs/mlflow_config.py +0 -0
  105. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/configs/mlops_manager.py +0 -0
  106. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/app.py +0 -0
  107. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/app_integrated.py +0 -0
  108. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/app_supabase.py +0 -0
  109. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/app_training.py +0 -0
  110. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/cli.py +0 -0
  111. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/common.py +0 -0
  112. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/components/charts.py +0 -0
  113. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/components/metrics.py +0 -0
  114. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/components/tables.py +0 -0
  115. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/overview.py +0 -0
  116. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/cicd.py +0 -0
  117. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/debug_dependencies.py +0 -0
  118. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/gravity_viz.py +0 -0
  119. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/monte_carlo_predictions.py +0 -0
  120. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/predictions_enhanced.py +0 -0
  121. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/scrapers_and_logs.py +0 -0
  122. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/test_portfolio.py +0 -0
  123. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/trading.py +0 -0
  124. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/pages/workflows.py +0 -0
  125. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/streamlit_extras_utils.py +0 -0
  126. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/styles.py +0 -0
  127. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/utils.py +0 -0
  128. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/dashboard/warning_suppression.py +0 -0
  129. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/data_ingestion/api_connectors.py +0 -0
  130. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/data_ingestion/data_pipeline.py +0 -0
  131. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/data_ingestion/stream_processor.py +0 -0
  132. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/database/migrations/env.py +0 -0
  133. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/database/models.py +0 -0
  134. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/database/session.py +0 -0
  135. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/experimentation/ab_testing.py +0 -0
  136. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/features/ensemble_features.py +0 -0
  137. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/features/political_features.py +0 -0
  138. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/features/recommendation_engine.py +0 -0
  139. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/features/stock_features.py +0 -0
  140. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/features/test_feature_engineering.py +0 -0
  141. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/logging.py +0 -0
  142. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/mlops/data_versioning.py +0 -0
  143. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/mlops/experiment_tracker.py +0 -0
  144. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/mlops/model_serving.py +0 -0
  145. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/mlops/pipeline_orchestrator.py +0 -0
  146. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/models/base_models.py +0 -0
  147. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/models/ensemble_models.py +0 -0
  148. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/models/recommendation_models.py +0 -0
  149. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/models/test_models.py +0 -0
  150. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/monitoring/drift_detection.py +0 -0
  151. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/monitoring/metrics.py +0 -0
  152. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/optimization/optimize.py +0 -0
  153. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/optimization/portfolio_optimizer.py +0 -0
  154. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/predictions/monte_carlo.py +0 -0
  155. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/predictions/prediction_engine.py +0 -0
  156. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/preprocessing/data_cleaners.py +0 -0
  157. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/preprocessing/feature_extractors.py +0 -0
  158. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/preprocessing/ml_pipeline.py +0 -0
  159. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/preprocessing/politician_trading_preprocessor.py +0 -0
  160. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/preprocessing/test_preprocessing.py +0 -0
  161. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/scripts/populate_sample_data.py +0 -0
  162. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/serving/serve.py +0 -0
  163. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/tasks.py +0 -0
  164. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/tests/test_integration.py +0 -0
  165. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/tests/test_training_dashboard.py +0 -0
  166. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/trading/alpaca_client.py +0 -0
  167. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/trading/migrations.py +0 -0
  168. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/trading/models.py +0 -0
  169. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/trading/paper_trading.py +0 -0
  170. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/trading/risk_management.py +0 -0
  171. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/trading/trading_service.py +0 -0
  172. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/training/train.py +0 -0
  173. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/ml/training/train_model.py +0 -0
  174. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/mygroup/test_cmd.py +0 -0
  175. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/public/oi/oi.py +0 -0
  176. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/public/public.py +0 -0
  177. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/self/completion_cmd.py +0 -0
  178. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/self/logs_cmd.py +0 -0
  179. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/self/redis_cmd.py +0 -0
  180. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/self/self_cmd.py +0 -0
  181. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/self/store_cmd.py +0 -0
  182. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/self/test_cmd.py +0 -0
  183. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/self/visual_cmd.py +0 -0
  184. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/self/zsh_cmd.py +0 -0
  185. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/async_command_database.py +0 -0
  186. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/async_process_manager.py +0 -0
  187. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/client.py +0 -0
  188. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/daemon.py +0 -0
  189. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/daemon_api.py +0 -0
  190. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/enhanced_daemon.py +0 -0
  191. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/process_cli.py +0 -0
  192. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/process_manager.py +0 -0
  193. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/daemon/test_daemon.py +0 -0
  194. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/dashboard/dashboard_cmd.py +0 -0
  195. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/docker/docker.py +0 -0
  196. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/gcloud/config.toml +0 -0
  197. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/gcloud/gcloud.py +0 -0
  198. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/git_commit/ai_service.py +0 -0
  199. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/lsh_integration.py +0 -0
  200. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/client.py +0 -0
  201. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/download_and_run_efficient_models.py +0 -0
  202. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/lightweight_embedder.py +0 -0
  203. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/lightweight_model_server.py +0 -0
  204. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/lightweight_test.py +0 -0
  205. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/model_service.py +0 -0
  206. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/ollama_efficient_runner.py +0 -0
  207. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/openai_adapter.py +0 -0
  208. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/pdf_processor.py +0 -0
  209. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/test_efficient_runner.py +0 -0
  210. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/test_example.py +0 -0
  211. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/test_integration.py +0 -0
  212. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/model_service/test_new_features.py +0 -0
  213. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/openai/openai.py +0 -0
  214. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/config.py +0 -0
  215. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/connectivity.py +0 -0
  216. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/data_sources.py +0 -0
  217. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/database.py +0 -0
  218. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/demo.py +0 -0
  219. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/models.py +0 -0
  220. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/monitoring.py +0 -0
  221. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/scrapers.py +0 -0
  222. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/scrapers_california.py +0 -0
  223. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/scrapers_corporate_registry.py +0 -0
  224. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/scrapers_eu.py +0 -0
  225. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/scrapers_free_sources.py +0 -0
  226. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/scrapers_third_party.py +0 -0
  227. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/scrapers_uk.py +0 -0
  228. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/scrapers_us_states.py +0 -0
  229. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/seed_database.py +0 -0
  230. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/supabase_functions.py +0 -0
  231. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/politician_trading/workflow.py +0 -0
  232. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/registry/registry.py +0 -0
  233. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/repo/repo.py +0 -0
  234. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/scheduler/cron_parser.py +0 -0
  235. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/scheduler/job.py +0 -0
  236. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/scheduler/monitor.py +0 -0
  237. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/scheduler/persistence.py +0 -0
  238. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/scheduler/scheduler.py +0 -0
  239. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/sync/test_cmd.py +0 -0
  240. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/wakatime/wakatime.py +0 -0
  241. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli/workflow/workflow.py +0 -0
  242. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli_framework.egg-info/dependency_links.txt +0 -0
  243. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli_framework.egg-info/entry_points.txt +0 -0
  244. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli_framework.egg-info/requires.txt +0 -0
  245. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/src/mcli_framework.egg-info/top_level.txt +0 -0
  246. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_all_commands.py +0 -0
  247. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_app_logs_cmd.py +0 -0
  248. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_app_redis_cmd.py +0 -0
  249. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_logs_cmd.py +0 -0
  250. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_main_app.py +0 -0
  251. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_model_cmd.py +0 -0
  252. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_self_cmd.py +0 -0
  253. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_self_cmd_commands.py +0 -0
  254. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_self_cmd_plugins.py +0 -0
  255. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_self_cmd_utilities.py +0 -0
  256. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_workflow_file.py +0 -0
  257. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_workflow_gcloud.py +0 -0
  258. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/cli/test_workflow_registry.py +0 -0
  259. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/conftest.py +0 -0
  260. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/demo_generate_graph.py +0 -0
  261. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/demo_hierarchical_transform.py +0 -0
  262. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/e2e/test_complete_workflows.py +0 -0
  263. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/e2e/test_model_workflow.py +0 -0
  264. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/e2e/test_new_user_workflow.py +0 -0
  265. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/e2e/test_update_workflow.py +0 -0
  266. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/fixtures/chat_fixtures.py +0 -0
  267. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/fixtures/cli_fixtures.py +0 -0
  268. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/fixtures/data_fixtures.py +0 -0
  269. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/fixtures/db_fixtures.py +0 -0
  270. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/fixtures/model_fixtures.py +0 -0
  271. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_agent.py +0 -0
  272. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_california_scraper.py +0 -0
  273. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_chat_client.py +0 -0
  274. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_chat_system.py +0 -0
  275. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_congress_scraper.py +0 -0
  276. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_daemon_client.py +0 -0
  277. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_daemon_server.py +0 -0
  278. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_e2e_dashboard_lsh_supabase.py +0 -0
  279. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_flask_webapp.py +0 -0
  280. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_gcloud_services.py +0 -0
  281. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_lsh_client.py +0 -0
  282. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_lsh_service.py +0 -0
  283. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_ml_auth.py +0 -0
  284. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_ml_data_pipeline.py +0 -0
  285. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_ml_models.py +0 -0
  286. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_ml_pipeline.py +0 -0
  287. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_module_imports.py +0 -0
  288. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_oi_service.py +0 -0
  289. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_politician_trading.py +0 -0
  290. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_repo_operations.py +0 -0
  291. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_scheduler_integration.py +0 -0
  292. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_service_registry.py +0 -0
  293. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_supabase_live_connection.py +0 -0
  294. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_uk_scraper.py +0 -0
  295. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_us_states_scraper.py +0 -0
  296. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_video_processing.py +0 -0
  297. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_wakatime_api.py +0 -0
  298. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_webapp_full.py +0 -0
  299. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_workflow.py +0 -0
  300. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/integration/test_workflow_commands.py +0 -0
  301. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/run_tests.py +0 -0
  302. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/test_harness.py +0 -0
  303. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/test_openai_adapter.py +0 -0
  304. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_api_utils.py +0 -0
  305. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_async_process_manager.py +0 -0
  306. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_auth_modules.py +0 -0
  307. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_bug_fixes.py +0 -0
  308. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_config.py +0 -0
  309. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_custom_commands.py +0 -0
  310. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_daemon_api.py +0 -0
  311. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_dashboard_components.py +0 -0
  312. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_dashboard_functions.py +0 -0
  313. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_dashboard_pages.py +0 -0
  314. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_dependencies.py +0 -0
  315. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_emulator_workflow.py +0 -0
  316. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_erd_generation.py +0 -0
  317. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_erd_generic.py +0 -0
  318. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_erd_imports.py +0 -0
  319. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_git_commit_workflow.py +0 -0
  320. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_lib_auth.py +0 -0
  321. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_lib_files.py +0 -0
  322. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_lib_utils.py +0 -0
  323. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_logger.py +0 -0
  324. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_ml_preprocessing.py +0 -0
  325. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_paths.py +0 -0
  326. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_pdf_compress.py +0 -0
  327. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_prediction_engine.py +0 -0
  328. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_regression.py +0 -0
  329. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_scheduler.py +0 -0
  330. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_scheduler_cron_parser.py +0 -0
  331. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_scheduler_job.py +0 -0
  332. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_scheduler_monitor.py +0 -0
  333. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_scheduler_persistence.py +0 -0
  334. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_self_update.py +0 -0
  335. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_store_cmd.py +0 -0
  336. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_supabase_connection.py +0 -0
  337. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_supabase_pagination.py +0 -0
  338. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_toml_utils.py +0 -0
  339. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_trading_imports.py +0 -0
  340. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_ui_rich.py +0 -0
  341. {mcli_framework-7.9.1 → mcli_framework-7.9.5}/tests/unit/test_uv_compat.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcli-framework
3
- Version: 7.9.1
3
+ Version: 7.9.5
4
4
  Summary: Portable workflow framework - transform any script into a versioned, schedulable command. Store in ~/.mcli/commands/, version with lockfile, run as daemon or cron job.
5
5
  Author-email: Luis Fernandez de la Vara <luis@lefv.io>
6
6
  Maintainer-email: Luis Fernandez de la Vara <luis@lefv.io>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mcli-framework"
3
- version = "7.9.1"
3
+ version = "7.9.5"
4
4
  description = "Portable workflow framework - transform any script into a versioned, schedulable command. Store in ~/.mcli/commands/, version with lockfile, run as daemon or cron job."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
@@ -0,0 +1,666 @@
1
+ """
2
+ Document conversion workflow with multiple fallback strategies and temp directory isolation.
3
+
4
+ A robust wrapper around pandoc, nbconvert, and other conversion tools
5
+ with automatic fallback to alternative methods when the primary method fails.
6
+ Uses temporary directory with hard links to avoid path issues.
7
+ """
8
+
9
+ import os
10
+ import shutil
11
+ import subprocess
12
+ import tempfile
13
+ from dataclasses import dataclass
14
+ from enum import Enum
15
+ from glob import glob as file_glob
16
+ from pathlib import Path
17
+ from typing import List, Optional, Tuple
18
+
19
+ import click
20
+
21
+ from mcli.lib.logger.logger import get_logger
22
+ from mcli.lib.paths import get_custom_commands_dir
23
+ from mcli.lib.ui.styling import error, info, success, warning
24
+
25
+ logger = get_logger()
26
+
27
+ # Format aliases to handle common abbreviations and file extensions
28
+ FORMAT_ALIASES = {
29
+ # Markdown variants
30
+ "md": "markdown",
31
+ "markdown": "markdown",
32
+ "gfm": "gfm", # GitHub Flavored Markdown
33
+ # Document formats
34
+ "doc": "docx",
35
+ "docx": "docx",
36
+ "odt": "odt",
37
+ # Markup formats
38
+ "html": "html",
39
+ "htm": "html",
40
+ "xhtml": "html",
41
+ # PDF
42
+ "pdf": "pdf",
43
+ # LaTeX
44
+ "tex": "latex",
45
+ "latex": "latex",
46
+ # Jupyter
47
+ "ipynb": "ipynb",
48
+ "notebook": "ipynb",
49
+ # Text formats
50
+ "txt": "plain",
51
+ "text": "plain",
52
+ "plain": "plain",
53
+ # Presentation formats
54
+ "pptx": "pptx",
55
+ "ppt": "pptx",
56
+ # Other formats
57
+ "rst": "rst",
58
+ "org": "org",
59
+ "mediawiki": "mediawiki",
60
+ "textile": "textile",
61
+ "rtf": "rtf",
62
+ "epub": "epub",
63
+ }
64
+
65
+
66
+ class ConversionMethod(Enum):
67
+ """Available conversion methods"""
68
+ PANDOC = "pandoc"
69
+ NBCONVERT = "nbconvert"
70
+ PANDOC_LATEX = "pandoc_latex"
71
+ PANDOC_HTML_INTERMEDIATE = "pandoc_html_intermediate"
72
+
73
+
74
+ @dataclass
75
+ class ConversionStrategy:
76
+ """Represents a conversion strategy with command and description"""
77
+ method: ConversionMethod
78
+ description: str
79
+ check_command: Optional[str] = None
80
+
81
+
82
+ def get_temp_conversion_dir() -> Path:
83
+ """Get or create temporary conversion directory in ~/.mcli/commands/temp/"""
84
+ commands_dir = get_custom_commands_dir()
85
+ temp_dir = commands_dir / "temp" / "conversions"
86
+ temp_dir.mkdir(parents=True, exist_ok=True)
87
+ return temp_dir
88
+
89
+
90
+ def create_temp_hardlink(source_path: Path) -> Tuple[Path, Path]:
91
+ """
92
+ Create a hard link to the source file in temp directory.
93
+
94
+ Returns: (temp_file_path, temp_dir_path)
95
+ """
96
+ temp_base = get_temp_conversion_dir()
97
+
98
+ # Create unique temp directory for this conversion
99
+ temp_dir = temp_base / f"conv_{os.getpid()}_{source_path.stem}"
100
+ temp_dir.mkdir(parents=True, exist_ok=True)
101
+
102
+ # Create hard link with simple name (avoids path issues)
103
+ temp_file = temp_dir / source_path.name
104
+
105
+ try:
106
+ # Try hard link first (most efficient)
107
+ os.link(source_path, temp_file)
108
+ logger.debug(f"Created hard link: {temp_file}")
109
+ except (OSError, NotImplementedError):
110
+ # Fall back to copy if hard link not supported (e.g., across filesystems)
111
+ shutil.copy2(source_path, temp_file)
112
+ logger.debug(f"Created copy (hard link not available): {temp_file}")
113
+
114
+ return temp_file, temp_dir
115
+
116
+
117
+ def cleanup_temp_conversion(temp_dir: Path, preserve_output: Optional[Path] = None):
118
+ """
119
+ Clean up temporary conversion directory.
120
+
121
+ Args:
122
+ temp_dir: Temporary directory to clean up
123
+ preserve_output: If specified, copy this file out before cleanup
124
+ """
125
+ try:
126
+ if preserve_output and preserve_output.exists():
127
+ # Output file is already in temp_dir, we'll handle it separately
128
+ pass
129
+
130
+ # Remove the entire temp directory
131
+ if temp_dir.exists():
132
+ shutil.rmtree(temp_dir)
133
+ logger.debug(f"Cleaned up temp directory: {temp_dir}")
134
+ except Exception as e:
135
+ logger.warning(f"Failed to clean up temp directory {temp_dir}: {e}")
136
+
137
+
138
+ def get_conversion_strategies(
139
+ input_path: Path,
140
+ output_path: Path,
141
+ from_format: str,
142
+ to_format: str,
143
+ pandoc_args: str = ""
144
+ ) -> List[ConversionStrategy]:
145
+ """
146
+ Get ordered list of conversion strategies to try based on input/output formats.
147
+
148
+ Returns strategies in priority order (most likely to succeed first).
149
+ """
150
+ strategies = []
151
+
152
+ # Special handling for Jupyter notebook to PDF (notoriously problematic)
153
+ if from_format == "ipynb" and to_format == "pdf":
154
+ # Strategy 1: nbconvert (most reliable for notebooks)
155
+ strategies.append(ConversionStrategy(
156
+ method=ConversionMethod.NBCONVERT,
157
+ description="jupyter nbconvert (best for notebooks)",
158
+ check_command="jupyter-nbconvert"
159
+ ))
160
+
161
+ # Strategy 2: pandoc with pdflatex
162
+ strategies.append(ConversionStrategy(
163
+ method=ConversionMethod.PANDOC_LATEX,
164
+ description="pandoc with pdflatex engine"
165
+ ))
166
+
167
+ # Strategy 3: pandoc via HTML intermediate
168
+ strategies.append(ConversionStrategy(
169
+ method=ConversionMethod.PANDOC_HTML_INTERMEDIATE,
170
+ description="pandoc via HTML intermediate (wkhtmltopdf)"
171
+ ))
172
+
173
+ # Strategy 4: standard pandoc
174
+ strategies.append(ConversionStrategy(
175
+ method=ConversionMethod.PANDOC,
176
+ description="pandoc default method"
177
+ ))
178
+
179
+ # Jupyter to other formats
180
+ elif from_format == "ipynb":
181
+ # Try nbconvert first for notebooks
182
+ strategies.append(ConversionStrategy(
183
+ method=ConversionMethod.NBCONVERT,
184
+ description="jupyter nbconvert",
185
+ check_command="jupyter-nbconvert"
186
+ ))
187
+ strategies.append(ConversionStrategy(
188
+ method=ConversionMethod.PANDOC,
189
+ description="pandoc"
190
+ ))
191
+
192
+ # PDF output (general)
193
+ elif to_format == "pdf":
194
+ strategies.append(ConversionStrategy(
195
+ method=ConversionMethod.PANDOC_LATEX,
196
+ description="pandoc with LaTeX"
197
+ ))
198
+ strategies.append(ConversionStrategy(
199
+ method=ConversionMethod.PANDOC,
200
+ description="pandoc default"
201
+ ))
202
+
203
+ # Default: just use pandoc
204
+ else:
205
+ strategies.append(ConversionStrategy(
206
+ method=ConversionMethod.PANDOC,
207
+ description="pandoc"
208
+ ))
209
+
210
+ return strategies
211
+
212
+
213
+ def execute_conversion_strategy(
214
+ strategy: ConversionStrategy,
215
+ input_path: Path,
216
+ output_path: Path,
217
+ from_format: str,
218
+ to_format: str,
219
+ pandoc_args: str = ""
220
+ ) -> Tuple[bool, str]:
221
+ """
222
+ Execute a specific conversion strategy in a temp directory.
223
+
224
+ Returns: (success: bool, error_message: str)
225
+ """
226
+ # Create temp hard link for conversion
227
+ temp_input, temp_dir = create_temp_hardlink(input_path)
228
+ temp_output = temp_dir / f"{input_path.stem}.{to_format.lower()}"
229
+
230
+ try:
231
+ if strategy.method == ConversionMethod.NBCONVERT:
232
+ # Check if nbconvert is available
233
+ check = subprocess.run(
234
+ ["jupyter", "nbconvert", "--version"],
235
+ capture_output=True,
236
+ timeout=5
237
+ )
238
+ if check.returncode != 0:
239
+ return False, "jupyter nbconvert not available"
240
+
241
+ # Build nbconvert command (run in temp directory)
242
+ cmd = [
243
+ "jupyter", "nbconvert",
244
+ "--to", to_format,
245
+ "--output", str(temp_output),
246
+ str(temp_input)
247
+ ]
248
+
249
+ # Run in temp directory
250
+ result = subprocess.run(
251
+ cmd,
252
+ capture_output=True,
253
+ text=True,
254
+ check=True,
255
+ timeout=120,
256
+ cwd=str(temp_dir)
257
+ )
258
+
259
+ elif strategy.method == ConversionMethod.PANDOC_LATEX:
260
+ # Pandoc with explicit LaTeX engine
261
+ cmd = [
262
+ "pandoc",
263
+ str(temp_input),
264
+ "-f", from_format,
265
+ "-t", "latex" if to_format == "pdf" else to_format,
266
+ "-o", str(temp_output),
267
+ "--pdf-engine=pdflatex"
268
+ ]
269
+ if pandoc_args:
270
+ cmd.extend(pandoc_args.split())
271
+
272
+ result = subprocess.run(
273
+ cmd,
274
+ capture_output=True,
275
+ text=True,
276
+ check=True,
277
+ timeout=120,
278
+ cwd=str(temp_dir)
279
+ )
280
+
281
+ elif strategy.method == ConversionMethod.PANDOC_HTML_INTERMEDIATE:
282
+ # Convert to HTML first, then to PDF
283
+ html_temp = temp_dir / f"{input_path.stem}_temp.html"
284
+
285
+ # Step 1: Convert to HTML
286
+ cmd_html = [
287
+ "pandoc",
288
+ str(temp_input),
289
+ "-f", from_format,
290
+ "-t", "html",
291
+ "-o", str(html_temp),
292
+ "--standalone"
293
+ ]
294
+ result = subprocess.run(
295
+ cmd_html,
296
+ capture_output=True,
297
+ text=True,
298
+ timeout=120,
299
+ cwd=str(temp_dir)
300
+ )
301
+ if result.returncode != 0:
302
+ return False, f"HTML intermediate failed: {result.stderr}"
303
+
304
+ # Step 2: Convert HTML to PDF
305
+ cmd = [
306
+ "pandoc",
307
+ str(html_temp),
308
+ "-f", "html",
309
+ "-t", "pdf",
310
+ "-o", str(temp_output)
311
+ ]
312
+
313
+ result = subprocess.run(
314
+ cmd,
315
+ capture_output=True,
316
+ text=True,
317
+ check=True,
318
+ timeout=120,
319
+ cwd=str(temp_dir)
320
+ )
321
+
322
+ else: # PANDOC
323
+ # Standard pandoc conversion
324
+ cmd = [
325
+ "pandoc",
326
+ str(temp_input),
327
+ "-f", from_format,
328
+ "-t", to_format,
329
+ "-o", str(temp_output)
330
+ ]
331
+ if pandoc_args:
332
+ cmd.extend(pandoc_args.split())
333
+
334
+ result = subprocess.run(
335
+ cmd,
336
+ capture_output=True,
337
+ text=True,
338
+ check=True,
339
+ timeout=120,
340
+ cwd=str(temp_dir)
341
+ )
342
+
343
+ # Copy output file to final destination
344
+ if temp_output.exists():
345
+ shutil.copy2(temp_output, output_path)
346
+ return True, ""
347
+ else:
348
+ return False, "Output file not created"
349
+
350
+ except subprocess.TimeoutExpired:
351
+ return False, "Conversion timed out (>120s)"
352
+ except subprocess.CalledProcessError as e:
353
+ return False, e.stderr or str(e)
354
+ except Exception as e:
355
+ return False, str(e)
356
+ finally:
357
+ # Always clean up temp directory
358
+ cleanup_temp_conversion(temp_dir)
359
+
360
+
361
+ @click.group(name="doc-convert")
362
+ def doc_convert():
363
+ """Document conversion with automatic fallback strategies"""
364
+ pass
365
+
366
+
367
+ @doc_convert.command()
368
+ def init():
369
+ """
370
+ Install all necessary dependencies for document conversion via Homebrew.
371
+
372
+ This will install:
373
+ - pandoc: Universal document converter
374
+ - basictex: LaTeX distribution for PDF generation
375
+ - jupyter & nbconvert: Best for converting Jupyter notebooks
376
+ """
377
+ info("=" * 60)
378
+ info("📦 Installing doc-convert dependencies")
379
+ info("=" * 60)
380
+ info("")
381
+
382
+ # Check if Homebrew is installed
383
+ try:
384
+ subprocess.run(["brew", "--version"], capture_output=True, check=True)
385
+ success("✅ Homebrew is installed")
386
+ except (subprocess.CalledProcessError, FileNotFoundError):
387
+ error("❌ Homebrew is not installed. Install it from https://brew.sh")
388
+ return
389
+
390
+ info("")
391
+
392
+ # Install pandoc
393
+ info("📥 Installing pandoc...")
394
+ try:
395
+ result = subprocess.run(["brew", "install", "pandoc"], capture_output=True, text=True)
396
+ if result.returncode == 0:
397
+ success(" ✅ pandoc installed successfully")
398
+ else:
399
+ check = subprocess.run(["which", "pandoc"], capture_output=True)
400
+ if check.returncode == 0:
401
+ info(" ℹ️ pandoc is already installed")
402
+ else:
403
+ error(f" ❌ Failed to install pandoc: {result.stderr}")
404
+ except Exception as e:
405
+ error(f" ❌ Error installing pandoc: {e}")
406
+
407
+ info("")
408
+
409
+ # Install Jupyter and nbconvert
410
+ info("📥 Installing Jupyter & nbconvert (for notebook conversion)...")
411
+ try:
412
+ # Check if already installed
413
+ check = subprocess.run(["jupyter", "nbconvert", "--version"], capture_output=True)
414
+ if check.returncode == 0:
415
+ info(" ℹ️ jupyter nbconvert is already installed")
416
+ else:
417
+ # Try installing via pip
418
+ result = subprocess.run(
419
+ ["pip3", "install", "jupyter", "nbconvert"],
420
+ capture_output=True,
421
+ text=True
422
+ )
423
+ if result.returncode == 0:
424
+ success(" ✅ jupyter & nbconvert installed successfully")
425
+ else:
426
+ warning(" ⚠️ Could not install jupyter via pip")
427
+ info(" ℹ️ You can install manually: pip3 install jupyter nbconvert")
428
+ except Exception as e:
429
+ warning(f" ⚠️ Error installing jupyter: {e}")
430
+ info(" ℹ️ Jupyter is optional but recommended for .ipynb conversions")
431
+
432
+ info("")
433
+
434
+ # Install BasicTeX (lightweight LaTeX for PDF support)
435
+ info("📥 Installing BasicTeX (for PDF generation)...")
436
+ info(" ℹ️ This is a large download (~100MB) and may take a few minutes")
437
+ try:
438
+ result = subprocess.run(
439
+ ["brew", "install", "--cask", "basictex"],
440
+ capture_output=True,
441
+ text=True
442
+ )
443
+ if result.returncode == 0:
444
+ success(" ✅ BasicTeX installed successfully")
445
+ info(" ℹ️ You may need to restart your terminal or run: eval $(/usr/libexec/path_helper)")
446
+ info("")
447
+ info(" 📦 Installing LaTeX packages for document conversion...")
448
+ info(" ℹ️ This requires sudo access and may take a few minutes")
449
+ info("")
450
+ info(" RECOMMENDED (installs all common packages + fonts):")
451
+ info(" sudo tlmgr install collection-latexextra collection-fontsrecommended")
452
+ info(" sudo mktexlsr")
453
+ info("")
454
+ info(" OR install individual packages:")
455
+ info(" sudo tlmgr install tcolorbox environ pgf tools pdfcol \\")
456
+ info(" adjustbox collectbox xkeyval \\")
457
+ info(" booktabs ulem titling enumitem soul \\")
458
+ info(" jknapltx rsfs")
459
+ info(" sudo tlmgr install collection-fontsrecommended")
460
+ info(" sudo mktexlsr")
461
+ else:
462
+ check = subprocess.run(["which", "pdflatex"], capture_output=True)
463
+ if check.returncode == 0:
464
+ info(" ℹ️ LaTeX is already installed")
465
+ else:
466
+ warning(" ⚠️ BasicTeX installation may have failed")
467
+ info(" ℹ️ You can skip this for non-PDF conversions")
468
+ except Exception as e:
469
+ warning(f" ⚠️ Error installing BasicTeX: {e}")
470
+ info(" ℹ️ BasicTeX is only needed for PDF conversions")
471
+
472
+ info("")
473
+ info("=" * 60)
474
+ success("✨ Installation complete!")
475
+ info("=" * 60)
476
+ info("")
477
+ info("Installed tools:")
478
+ info(" • pandoc - Universal document converter")
479
+ info(" • jupyter nbconvert - Best for Jupyter notebooks")
480
+ info(" • basictex - LaTeX for PDF generation")
481
+ info("")
482
+ info("⚠️ IMPORTANT: For Jupyter notebook → PDF conversions:")
483
+ info(" Install required LaTeX packages (requires sudo):")
484
+ info("")
485
+ info(" RECOMMENDED (installs all common packages + fonts):")
486
+ info(" sudo tlmgr install collection-latexextra collection-fontsrecommended")
487
+ info(" sudo mktexlsr")
488
+ info("")
489
+ info(" OR install individual packages:")
490
+ info(" sudo tlmgr install tcolorbox environ pgf tools pdfcol \\")
491
+ info(" adjustbox collectbox xkeyval \\")
492
+ info(" booktabs ulem titling enumitem soul \\")
493
+ info(" jknapltx rsfs")
494
+ info(" sudo tlmgr install collection-fontsrecommended")
495
+ info(" sudo mktexlsr")
496
+ info("")
497
+ info("You can now use: mcli workflow doc-convert convert <from> <to> <file>")
498
+ info("Example: mcli workflow doc-convert convert ipynb pdf notebook.ipynb")
499
+ info("")
500
+
501
+
502
+ @doc_convert.command()
503
+ @click.argument("from_format")
504
+ @click.argument("to_format")
505
+ @click.argument("path")
506
+ @click.option("--output-dir", "-o", help="Output directory (defaults to same directory as input)")
507
+ @click.option("--pandoc-args", "-a", help="Additional pandoc arguments", default="")
508
+ @click.option("--no-fallback", is_flag=True, help="Disable fallback strategies (use only primary method)")
509
+ def convert(from_format, to_format, path, output_dir, pandoc_args, no_fallback):
510
+ """
511
+ Convert documents with automatic fallback strategies.
512
+
513
+ FROM_FORMAT: Source format (e.g., ipynb, md, docx, html)
514
+
515
+ TO_FORMAT: Target format (e.g., pdf, html, md, docx)
516
+
517
+ PATH: File path or glob pattern (e.g., "*.ipynb" or "./notebook.ipynb")
518
+
519
+ The converter will try multiple conversion methods automatically:
520
+ - For Jupyter notebooks: tries nbconvert, then pandoc with various engines
521
+ - For PDF output: tries LaTeX engine, then alternative methods
522
+ - Falls back gracefully when primary method fails
523
+
524
+ All conversions are performed in a temporary directory to avoid path issues
525
+ with spaces or special characters.
526
+
527
+ Examples:
528
+
529
+ # Convert Jupyter notebook to PDF (tries nbconvert first)
530
+ mcli workflow doc-convert convert ipynb pdf notebook.ipynb
531
+
532
+ # Convert markdown to HTML
533
+ mcli workflow doc-convert convert md html README.md
534
+
535
+ # Convert all markdown files with custom output directory
536
+ mcli workflow doc-convert convert md pdf "*.md" -o ./pdfs
537
+ """
538
+ # Check if pandoc is installed (primary tool)
539
+ has_pandoc = False
540
+ try:
541
+ subprocess.run(["pandoc", "--version"], capture_output=True, check=True)
542
+ has_pandoc = True
543
+ except (subprocess.CalledProcessError, FileNotFoundError):
544
+ pass
545
+
546
+ # Check if nbconvert is available
547
+ has_nbconvert = False
548
+ try:
549
+ subprocess.run(["jupyter", "nbconvert", "--version"], capture_output=True, check=True)
550
+ has_nbconvert = True
551
+ except (subprocess.CalledProcessError, FileNotFoundError):
552
+ pass
553
+
554
+ # Require at least one conversion tool
555
+ if not has_pandoc and not has_nbconvert:
556
+ error("❌ No conversion tools found!")
557
+ error(" Install with: mcli workflow doc-convert init")
558
+ error(" Or: brew install pandoc")
559
+ return
560
+
561
+ # Map format aliases
562
+ from_format_mapped = FORMAT_ALIASES.get(from_format.lower(), from_format)
563
+ to_format_mapped = FORMAT_ALIASES.get(to_format.lower(), to_format)
564
+ output_ext = to_format.lower()
565
+
566
+ # Expand path
567
+ expanded_path = os.path.expanduser(path)
568
+
569
+ # Handle glob patterns
570
+ if "*" in expanded_path or "?" in expanded_path or "[" in expanded_path:
571
+ files = file_glob(expanded_path, recursive=True)
572
+ if not files:
573
+ error(f"❌ No files found matching pattern: {path}")
574
+ return
575
+ info(f"📁 Found {len(files)} file(s) matching pattern: {path}")
576
+ else:
577
+ files = [expanded_path]
578
+
579
+ # Process each file
580
+ success_count = 0
581
+ error_count = 0
582
+ conversion_methods_used = {}
583
+
584
+ for input_file in files:
585
+ input_path = Path(input_file).resolve() # Get absolute path
586
+
587
+ if not input_path.exists():
588
+ warning(f"⚠️ File not found: {input_file}")
589
+ error_count += 1
590
+ continue
591
+
592
+ # Determine output path
593
+ if output_dir:
594
+ output_path = Path(output_dir) / f"{input_path.stem}.{output_ext}"
595
+ os.makedirs(output_dir, exist_ok=True)
596
+ else:
597
+ output_path = input_path.parent / f"{input_path.stem}.{output_ext}"
598
+
599
+ info(f"🔄 Converting: {input_path.name} → {output_path.name}")
600
+ info(f" 📁 Using temp directory: ~/.mcli/commands/temp/conversions/")
601
+
602
+ # Get conversion strategies
603
+ strategies = get_conversion_strategies(
604
+ input_path, output_path, from_format_mapped, to_format_mapped, pandoc_args
605
+ )
606
+
607
+ # Limit to first strategy if no-fallback is set
608
+ if no_fallback:
609
+ strategies = strategies[:1]
610
+
611
+ # Try each strategy in order
612
+ conversion_succeeded = False
613
+ last_error = ""
614
+
615
+ for i, strategy in enumerate(strategies):
616
+ if i > 0:
617
+ info(f" ⚙️ Trying fallback method: {strategy.description}")
618
+ else:
619
+ info(f" ⚙️ Using: {strategy.description}")
620
+
621
+ success_flag, error_msg = execute_conversion_strategy(
622
+ strategy, input_path, output_path,
623
+ from_format_mapped, to_format_mapped, pandoc_args
624
+ )
625
+
626
+ if success_flag:
627
+ conversion_succeeded = True
628
+ method_name = strategy.description
629
+ conversion_methods_used[method_name] = conversion_methods_used.get(method_name, 0) + 1
630
+ success(f" ✅ Created: {output_path}")
631
+ if i > 0:
632
+ info(f" ℹ️ Succeeded with fallback method #{i + 1}")
633
+ break
634
+ else:
635
+ last_error = error_msg
636
+ if i < len(strategies) - 1:
637
+ warning(f" ⚠️ {strategy.description} failed, trying next method...")
638
+
639
+ if conversion_succeeded:
640
+ success_count += 1
641
+ else:
642
+ error(f" ❌ All conversion methods failed")
643
+ if last_error:
644
+ error(f" ℹ️ Last error: {last_error[:200]}")
645
+ error_count += 1
646
+
647
+ # Summary
648
+ info("")
649
+ info("=" * 60)
650
+ success("✨ Conversion complete!")
651
+ info(f" ✅ Successful: {success_count}")
652
+ if error_count > 0:
653
+ error(f" ❌ Failed: {error_count}")
654
+
655
+ # Show which methods were used
656
+ if conversion_methods_used:
657
+ info("")
658
+ info("Methods used:")
659
+ for method, count in conversion_methods_used.items():
660
+ info(f" • {method}: {count} file(s)")
661
+
662
+ info("=" * 60)
663
+
664
+
665
+ if __name__ == "__main__":
666
+ doc_convert()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcli-framework
3
- Version: 7.9.1
3
+ Version: 7.9.5
4
4
  Summary: Portable workflow framework - transform any script into a versioned, schedulable command. Store in ~/.mcli/commands/, version with lockfile, run as daemon or cron job.
5
5
  Author-email: Luis Fernandez de la Vara <luis@lefv.io>
6
6
  Maintainer-email: Luis Fernandez de la Vara <luis@lefv.io>