bertrend 0.3.20__tar.gz → 0.3.22__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 (288) hide show
  1. {bertrend-0.3.20 → bertrend-0.3.22}/PKG-INFO +4 -1
  2. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/__init__.py +28 -13
  3. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/i18n.py +22 -15
  4. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/start_summarizer_app.sh +1 -1
  5. bertrend-0.3.22/bertrend/demos/start_topic_analysis_app.sh +36 -0
  6. bertrend-0.3.22/bertrend/demos/start_weak_signals_app.sh +36 -0
  7. bertrend-0.3.22/bertrend/services/scheduling/.dockerignore +52 -0
  8. bertrend-0.3.22/bertrend/services/scheduling/Docker_setup.md +310 -0
  9. bertrend-0.3.22/bertrend/services/scheduling/Dockerfile +29 -0
  10. bertrend-0.3.22/bertrend/services/scheduling/dashboard.html +698 -0
  11. bertrend-0.3.22/bertrend/services/scheduling/docker-compose.yml +53 -0
  12. bertrend-0.3.22/bertrend/services/scheduling/job_utils/job_functions.py +54 -0
  13. bertrend-0.3.22/bertrend/services/scheduling/models/scheduling_models.py +137 -0
  14. bertrend-0.3.22/bertrend/services/scheduling/requirements.txt +7 -0
  15. bertrend-0.3.22/bertrend/services/scheduling/routers/info.py +20 -0
  16. bertrend-0.3.22/bertrend/services/scheduling/routers/scheduling.py +644 -0
  17. bertrend-0.3.22/bertrend/services/scheduling/scheduling_service.py +22 -0
  18. bertrend-0.3.22/bertrend/tests/apps/test_bertrend_service.py +293 -0
  19. bertrend-0.3.22/bertrend/tests/apps/test_models.py +208 -0
  20. {bertrend-0.3.20/bertrend_apps/tests → bertrend-0.3.22/bertrend/tests/apps}/test_process_new_data.py +27 -19
  21. bertrend-0.3.22/bertrend/tests/apps/test_routers_bertrend_app.py +285 -0
  22. bertrend-0.3.22/bertrend/tests/apps/test_routers_info.py +39 -0
  23. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/tests/conftest.py +0 -2
  24. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_temporal_metrics_embedding.py +257 -9
  25. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_topic_metrics.py +0 -2
  26. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_visualizations.py +0 -1
  27. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_agent_utils.py +1 -3
  28. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_article_scoring.py +5 -1
  29. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_newsletter_features.py +5 -0
  30. bertrend-0.3.22/bertrend/tests/services/scheduling/__init__.py +4 -0
  31. bertrend-0.3.22/bertrend/tests/services/scheduling/test_scheduling_service.py +256 -0
  32. bertrend-0.3.22/bertrend/tests/services/summarizer/__init__.py +4 -0
  33. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/summarizer}/test_abstractive_summarizer.py +1 -1
  34. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/summarizer}/test_extractive_summarizer.py +1 -5
  35. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/tests/test_integration.py +43 -50
  36. bertrend-0.3.22/bertrend/tests/utils/__init__.py +4 -0
  37. bertrend-0.3.22/bertrend/tests/utils/test_apscheduler_utils.py +578 -0
  38. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/utils}/test_cache_utils.py +1 -1
  39. bertrend-0.3.22/bertrend/tests/utils/test_crontab_utils.py +454 -0
  40. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/utils}/test_data_loading.py +1 -2
  41. bertrend-0.3.22/bertrend/tests/utils/test_date_utils.py +169 -0
  42. bertrend-0.3.22/bertrend/tests/utils/test_mail_utils.py +354 -0
  43. bertrend-0.3.22/bertrend/tests/utils/test_scheduler_utils.py +220 -0
  44. bertrend-0.3.22/bertrend/topic_analysis/__init__.py +4 -0
  45. bertrend-0.3.22/bertrend/trend_analysis/__init__.py +4 -0
  46. bertrend-0.3.22/bertrend_apps/__init__.py +36 -0
  47. bertrend-0.3.22/bertrend_apps/common/__init__.py +4 -0
  48. bertrend-0.3.22/bertrend_apps/common/apscheduler_utils.py +321 -0
  49. bertrend-0.3.22/bertrend_apps/common/crontab_utils.py +187 -0
  50. bertrend-0.3.22/bertrend_apps/common/date_utils.py +25 -0
  51. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/common/mail_utils.py +6 -2
  52. bertrend-0.3.22/bertrend_apps/common/scheduler_utils.py +153 -0
  53. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/__init__.py +2 -0
  54. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/__main__.py +24 -115
  55. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/arxiv_provider.py +2 -2
  56. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/data_provider.py +6 -2
  57. bertrend-0.3.22/bertrend_apps/data_provider/data_provider_utils.py +172 -0
  58. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/newscatcher_provider.py +1 -1
  59. bertrend-0.3.22/bertrend_apps/exploration/__init__.py +4 -0
  60. bertrend-0.3.22/bertrend_apps/exploration/curebot/__init__.py +4 -0
  61. bertrend-0.3.22/bertrend_apps/exploration/start_apps.sh +36 -0
  62. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/install_feeds_and_newsletters.py +3 -3
  63. bertrend-0.3.22/bertrend_apps/newsletters/__init__.py +4 -0
  64. bertrend-0.3.22/bertrend_apps/newsletters/__main__.py +48 -0
  65. bertrend-0.3.22/bertrend_apps/newsletters/newsletter_generation.py +191 -0
  66. bertrend-0.3.22/bertrend_apps/newsletters/utils.py +84 -0
  67. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/__init__.py +1 -2
  68. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/app.py +2 -2
  69. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/automated_report_generation.py +33 -16
  70. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/dashboard_analysis.py +1 -4
  71. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/dashboard_common.py +1 -1
  72. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/dashboard_comparative.py +67 -44
  73. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/dashboard_signals.py +1 -1
  74. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/feeds_config.py +21 -21
  75. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/feeds_data.py +1 -1
  76. bertrend-0.3.22/bertrend_apps/prospective_demo/i18n.py +40 -0
  77. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/i18n_translations.py +88 -0
  78. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/models_info.py +52 -144
  79. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/process_new_data.py +156 -60
  80. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/report_generation.py +7 -41
  81. bertrend-0.3.22/bertrend_apps/prospective_demo/report_generation_utils.py +46 -0
  82. bertrend-0.3.22/bertrend_apps/prospective_demo/start_demo.sh +36 -0
  83. bertrend-0.3.22/bertrend_apps/services/__init__.py +4 -0
  84. bertrend-0.3.22/bertrend_apps/services/bertrend_service.py +19 -0
  85. bertrend-0.3.22/bertrend_apps/services/config/default_config.toml +4 -0
  86. bertrend-0.3.22/bertrend_apps/services/config/settings.py +33 -0
  87. bertrend-0.3.22/bertrend_apps/services/models/__init__.py +4 -0
  88. bertrend-0.3.22/bertrend_apps/services/models/bertrend_app_models.py +54 -0
  89. bertrend-0.3.22/bertrend_apps/services/models/data_provider_models.py +66 -0
  90. bertrend-0.3.22/bertrend_apps/services/models/newsletters_models.py +34 -0
  91. bertrend-0.3.22/bertrend_apps/services/routers/__init__.py +4 -0
  92. bertrend-0.3.22/bertrend_apps/services/routers/bertrend_app.py +140 -0
  93. bertrend-0.3.22/bertrend_apps/services/routers/data_provider.py +157 -0
  94. bertrend-0.3.22/bertrend_apps/services/routers/info.py +29 -0
  95. bertrend-0.3.22/bertrend_apps/services/routers/newsletters.py +66 -0
  96. bertrend-0.3.22/bertrend_apps/services/start.py +24 -0
  97. bertrend-0.3.22/bertrend_apps/services/status.py +30 -0
  98. bertrend-0.3.22/bertrend_apps/services/stop.py +14 -0
  99. bertrend-0.3.22/bertrend_apps/services/utils/__init__.py +4 -0
  100. bertrend-0.3.22/bertrend_apps/services/utils/logging_utils.py +30 -0
  101. {bertrend-0.3.20 → bertrend-0.3.22}/pyproject.toml +4 -1
  102. bertrend-0.3.20/bertrend/demos/start_topic_analysis_app.sh +0 -14
  103. bertrend-0.3.20/bertrend/demos/start_weak_signals_app.sh +0 -14
  104. bertrend-0.3.20/bertrend/tests/test_mail_utils.py +0 -468
  105. bertrend-0.3.20/bertrend_apps/common/crontab_utils.py +0 -141
  106. bertrend-0.3.20/bertrend_apps/newsletters/__main__.py +0 -293
  107. bertrend-0.3.20/bertrend_apps/prospective_demo/start_demo.sh +0 -16
  108. bertrend-0.3.20/bertrend_apps/start_apps.sh +0 -15
  109. {bertrend-0.3.20 → bertrend-0.3.22}/AUTHORS.txt +0 -0
  110. {bertrend-0.3.20 → bertrend-0.3.22}/LICENSE.md +0 -0
  111. {bertrend-0.3.20 → bertrend-0.3.22}/README.md +0 -0
  112. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/BERTopicModel.py +0 -0
  113. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/BERTrend.py +0 -0
  114. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/article_scoring/__init__.py +0 -0
  115. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/article_scoring/article_scoring.py +0 -0
  116. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/article_scoring/prompts.py +0 -0
  117. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/article_scoring/scoring_agent.py +0 -0
  118. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/config/bertopic_default_config.toml +0 -0
  119. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/config/bertrend_default_config.toml +0 -0
  120. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/config/parameters.py +0 -0
  121. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/config/services_default_config.toml +0 -0
  122. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/__init__.py +0 -0
  123. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/__init__.py +0 -0
  124. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/data_loading_component.py +0 -0
  125. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/embed_documents_component.py +0 -0
  126. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/i18n_translations.py +0 -0
  127. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/icons.py +0 -0
  128. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/parameters_component.py +0 -0
  129. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/demos_utils/state_utils.py +0 -0
  130. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/streamlit_components/__init__.py +0 -0
  131. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/streamlit_components/clickable_df_component.py +0 -0
  132. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/streamlit_components/input_with_pills_component.py +0 -0
  133. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/summarization/__init__.py +0 -0
  134. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/summarization/summarizer_app.py +0 -0
  135. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/.streamlit/config.toml +0 -0
  136. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/__init__.py +0 -0
  137. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/app.py +0 -0
  138. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/app_utils.py +0 -0
  139. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/__init__.py +0 -0
  140. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/explore_topics.py +0 -0
  141. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/newsletters_generation.py +0 -0
  142. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/temporal_visualizations.py +0 -0
  143. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/topic_visualizations.py +0 -0
  144. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/demo_pages/training_page.py +0 -0
  145. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/topic_analysis/i18n_translations.py +0 -0
  146. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/.streamlit/config.toml +0 -0
  147. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/__init__.py +0 -0
  148. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/app.py +0 -0
  149. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/i18n_translations.py +0 -0
  150. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/demos/weak_signals/visualizations_utils.py +0 -0
  151. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/__init__.py +0 -0
  152. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/agent_utils.py +0 -0
  153. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter.css +0 -0
  154. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter_features.py +0 -0
  155. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter_model.py +0 -0
  156. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter_outlook_template.html +0 -0
  157. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/newsletter_template.html +0 -0
  158. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/openai_client.py +0 -0
  159. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/llm_utils/prompts.py +0 -0
  160. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/metrics/__init__.py +0 -0
  161. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/metrics/temporal_metrics_embedding.py +0 -0
  162. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/metrics/topic_metrics.py +0 -0
  163. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/resources/common_ngrams.json +0 -0
  164. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/resources/stopwords-en.json +0 -0
  165. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/resources/stopwords-fr.json +0 -0
  166. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/resources/stopwords-rte.json +0 -0
  167. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/__init__.py +0 -0
  168. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/authentication.py +0 -0
  169. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/cert.pem +0 -0
  170. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_client.py +0 -0
  171. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/README.md +0 -0
  172. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/__init__.py +0 -0
  173. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/bertrend_client_registry.json +0 -0
  174. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/config/default_config.toml +0 -0
  175. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/config/settings.py +0 -0
  176. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/main.py +0 -0
  177. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/models.py +0 -0
  178. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/requirements.txt +0 -0
  179. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/routers/__init__.py +0 -0
  180. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/routers/authentication.py +0 -0
  181. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/routers/embeddings.py +0 -0
  182. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/routers/info.py +0 -0
  183. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/security.py +0 -0
  184. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/start.py +0 -0
  185. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/status.py +0 -0
  186. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_server/stop.py +0 -0
  187. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/embedding_service.py +0 -0
  188. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/key.pem +0 -0
  189. {bertrend-0.3.20/bertrend/services/summary → bertrend-0.3.22/bertrend/services/scheduling}/__init__.py +0 -0
  190. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/services/scheduling/job_utils}/__init__.py +0 -0
  191. {bertrend-0.3.20/bertrend/topic_analysis → bertrend-0.3.22/bertrend/services/scheduling/models}/__init__.py +0 -0
  192. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summarizer.py +0 -0
  193. {bertrend-0.3.20/bertrend/trend_analysis → bertrend-0.3.22/bertrend/services/summary}/__init__.py +0 -0
  194. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/abstractive_summarizer.py +0 -0
  195. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/chatgpt_summarizer.py +0 -0
  196. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/extractive_summarizer.py +0 -0
  197. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/lexrank.py +0 -0
  198. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/services/summary/prompts.py +0 -0
  199. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/tests/README_integration_tests.md +0 -0
  200. {bertrend-0.3.20/bertrend_apps → bertrend-0.3.22/bertrend/tests}/__init__.py +0 -0
  201. {bertrend-0.3.20/bertrend_apps/common → bertrend-0.3.22/bertrend/tests/apps}/__init__.py +0 -0
  202. {bertrend-0.3.20/bertrend_apps/exploration → bertrend-0.3.22/bertrend/tests/core}/__init__.py +0 -0
  203. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_bertrend.py +0 -0
  204. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_data_structure.py +0 -0
  205. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_representative_docs.py +0 -0
  206. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_topic_description.py +0 -0
  207. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_topic_model.py +0 -0
  208. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_trend_analysis_data_structure.py +0 -0
  209. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_trend_analysis_prompts.py +0 -0
  210. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_trend_analysis_visualizations.py +0 -0
  211. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/core}/test_trend_analysis_weak_signals.py +0 -0
  212. {bertrend-0.3.20/bertrend_apps/exploration/curebot → bertrend-0.3.22/bertrend/tests/llm}/__init__.py +0 -0
  213. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_article_scoring_models.py +0 -0
  214. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_newsletter_model.py +0 -0
  215. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/llm}/test_openai_client.py +0 -0
  216. {bertrend-0.3.20/bertrend_apps/newsletters → bertrend-0.3.22/bertrend/tests/services}/__init__.py +0 -0
  217. {bertrend-0.3.20/bertrend_apps/tests → bertrend-0.3.22/bertrend/tests/services/embedding}/__init__.py +0 -0
  218. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/embedding}/test_embedding_client.py +0 -0
  219. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/summarizer}/test_chatgpt_summarizer.py +0 -0
  220. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/services/summarizer}/test_summarizer.py +0 -0
  221. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/tests/test_installation.py +0 -0
  222. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/utils}/test_config_utils.py +0 -0
  223. {bertrend-0.3.20/bertrend/tests → bertrend-0.3.22/bertrend/tests/utils}/test_utils_init.py +0 -0
  224. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/data_structure.py +0 -0
  225. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/prompts.py +0 -0
  226. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/representative_docs.py +0 -0
  227. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/topic_description.py +0 -0
  228. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/topic_analysis/visualizations.py +0 -0
  229. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/data_structure.py +0 -0
  230. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/prompts.py +0 -0
  231. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/signal_llm_template_en.html +0 -0
  232. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/signal_llm_template_fr.html +0 -0
  233. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/visualizations.py +0 -0
  234. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/trend_analysis/weak_signals.py +0 -0
  235. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/utils/__init__.py +0 -0
  236. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/utils/cache_utils.py +0 -0
  237. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/utils/config_utils.py +0 -0
  238. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend/utils/data_loading.py +0 -0
  239. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/arxiv_feed.toml +0 -0
  240. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/decarbonation_feed.toml +0 -0
  241. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/llm_en_feed.toml +0 -0
  242. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/llm_feed.toml +0 -0
  243. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/nlp_feed.toml +0 -0
  244. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/feeds/rte_feed.toml +0 -0
  245. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/arxiv_newsletter_from_last.toml +0 -0
  246. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/decarbonation_newsletter_from_last.toml +0 -0
  247. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/decarbonation_newsletter_from_scratch.toml +0 -0
  248. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/llm_en_newsletter_from_last.toml +0 -0
  249. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/llm_newsletter_from_last.toml +0 -0
  250. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/nlp_newsletter_from_last.toml +0 -0
  251. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/rte_newsletter_from_last.toml +0 -0
  252. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/config/newsletters/rte_newsletter_from_scratch.toml +0 -0
  253. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/atom_feed_provider.py +0 -0
  254. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/bing_news_provider.py +0 -0
  255. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/google_news_provider.py +0 -0
  256. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/rss_feed_provider.py +0 -0
  257. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/data_provider/utils.py +0 -0
  258. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/.streamlit/config.toml +0 -0
  259. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/app.py +0 -0
  260. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/app_utils.py +0 -0
  261. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/config.toml +0 -0
  262. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/import_extraction_article.ipynb +0 -0
  263. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/prompts.py +0 -0
  264. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/start_newsletter_generator.sh +0 -0
  265. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/tabs/tab1.py +0 -0
  266. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/tabs/tab2.py +0 -0
  267. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/curebot/tabs/tab3.py +0 -0
  268. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/dataviz/Main_page.py +0 -0
  269. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/dataviz/__init__.py +0 -0
  270. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/dataviz/pages/1_Data_feeds.py +0 -0
  271. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/__init__.py +0 -0
  272. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/entity_utils.py +0 -0
  273. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/__init__.py +0 -0
  274. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/common_factory.py +0 -0
  275. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/dbpedia.py +0 -0
  276. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/nlp.config +0 -0
  277. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/exploration/geolocalization/spacy/utils.py +0 -0
  278. {bertrend-0.3.20/bertrend_apps → bertrend-0.3.22/bertrend_apps/exploration}/stop_apps.sh +0 -0
  279. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/.streamlit/config.toml +0 -0
  280. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/.streamlit/secrets.toml +0 -0
  281. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/authentication.py +0 -0
  282. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/data_model.py +0 -0
  283. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/detailed_report_template.html +0 -0
  284. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/docs/automated_report_generation.md +0 -0
  285. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/feeds_common.py +0 -0
  286. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/llm_utils.py +0 -0
  287. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/perf_utils.py +0 -0
  288. {bertrend-0.3.20 → bertrend-0.3.22}/bertrend_apps/prospective_demo/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bertrend
3
- Version: 0.3.20
3
+ Version: 0.3.22
4
4
  Summary: BERTrend analyses topic evolution over time using state-of-the-art transformer models: topic modelling and LLM
5
5
  License: LICENSE.md
6
6
  License-File: AUTHORS.txt
@@ -13,8 +13,10 @@ Maintainer-email: jerome.picault@rte-france.com
13
13
  Requires-Python: >=3.12,<4.0
14
14
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
15
  Provides-Extra: apps
16
+ Requires-Dist: APScheduler (>=3.11.0)
16
17
  Requires-Dist: PyJWT (>=2.10.1)
17
18
  Requires-Dist: Pyqtree (==1.0.0)
19
+ Requires-Dist: SQLAlchemy (>=2.0.40)
18
20
  Requires-Dist: arxiv (>=2.2.0) ; extra == "apps"
19
21
  Requires-Dist: bertopic (==0.16.2)
20
22
  Requires-Dist: black (>=24.10.0)
@@ -24,6 +26,7 @@ Requires-Dist: dask (==2024.12.0)
24
26
  Requires-Dist: datamapplot (==0.3.0)
25
27
  Requires-Dist: dateparser (>=1.2.0)
26
28
  Requires-Dist: dill (>=0.4.0)
29
+ Requires-Dist: fastapi (>=0.120.0)
27
30
  Requires-Dist: feedparser (>=6.0.11) ; extra == "apps"
28
31
  Requires-Dist: gensim (>=4.3.3)
29
32
  Requires-Dist: google-api-python-client (>=2.148.0) ; extra == "apps"
@@ -3,20 +3,39 @@
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
  # This file is part of BERTrend.
5
5
  import os
6
+ import sys
6
7
  from pathlib import Path
7
8
 
8
9
  from loguru import logger
9
10
 
11
+
12
+ # Global flag to track initialization
13
+ _initialized = False
14
+
10
15
  # Auto-load .env if python-dotenv is available
11
- try:
12
- from dotenv import load_dotenv # type: ignore
16
+ if not _initialized:
17
+ try:
18
+ from dotenv import load_dotenv # type: ignore
19
+
20
+ if load_dotenv(override=True):
21
+ logger.info("Loaded .env file")
22
+ else:
23
+ logger.warning("Failed to load .env file")
24
+
25
+ except Exception:
26
+ pass
13
27
 
14
- if load_dotenv(override=True):
15
- logger.info("Loaded .env file")
16
- else:
17
- logger.warning("Failed to load .env file")
18
- except Exception:
19
- pass
28
+ # First, remove the default handler (Loguru always adds one by default)
29
+ logger.remove()
30
+
31
+ # Add back a colorized stdout sink
32
+ logger.add(
33
+ sys.stdout,
34
+ colorize=True,
35
+ format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
36
+ )
37
+
38
+ _initialized = True
20
39
 
21
40
  from bertrend.utils.config_utils import load_toml_config
22
41
 
@@ -43,11 +62,7 @@ LLM_CONFIG = SERVICES_CONFIG["llm_service"]
43
62
  BEST_CUDA_DEVICE = r"\`nvidia-smi --query-gpu=index,memory.used --format=csv,nounits | tail -n +2 | sort -t',' -k2 -n | head -n 1 | cut -d',' -f1\`"
44
63
 
45
64
  BERTREND_BASE_DIR = os.getenv("BERTREND_BASE_DIR", None)
46
- BASE_PATH = (
47
- Path(BERTREND_BASE_DIR)
48
- if BERTREND_BASE_DIR
49
- else Path(__file__).parent.parent.parent
50
- )
65
+ BASE_PATH = Path(BERTREND_BASE_DIR) if BERTREND_BASE_DIR else Path.home() / ".bertrend"
51
66
 
52
67
  # Base dirs
53
68
  DATA_PATH = BASE_PATH / "data"
@@ -8,12 +8,10 @@ Provides functionality for translating text between French and English.
8
8
  # SPDX-License-Identifier: MPL-2.0
9
9
  # This file is part of BERTrend.
10
10
 
11
- import streamlit as st
12
11
  from typing import Optional
13
12
 
14
- from bertrend_apps.prospective_demo.i18n_translations import (
15
- TRANSLATIONS as PROSPECTIVE_TRANSLATIONS,
16
- )
13
+ import streamlit as st
14
+
17
15
  from bertrend.demos.topic_analysis.i18n_translations import (
18
16
  TRANSLATIONS as TOPIC_ANALYSIS_TRANSLATIONS,
19
17
  )
@@ -26,9 +24,8 @@ from bertrend.demos.weak_signals.i18n_translations import (
26
24
 
27
25
  # Merge all translations
28
26
  TRANSLATIONS = {
29
- **PROSPECTIVE_TRANSLATIONS,
30
- **TOPIC_ANALYSIS_TRANSLATIONS,
31
27
  **DEMOS_UTILS_TRANSLATIONS,
28
+ **TOPIC_ANALYSIS_TRANSLATIONS,
32
29
  **WEAK_SIGNALS_TRANSLATIONS,
33
30
  }
34
31
 
@@ -39,12 +36,6 @@ LANGUAGES = {"fr": "Français", "en": "English"}
39
36
  DEFAULT_LANGUAGE = "en"
40
37
 
41
38
 
42
- def set_default_internationalization_language(language: str) -> None:
43
- """Set the default language for the application."""
44
- global DEFAULT_LANGUAGE
45
- DEFAULT_LANGUAGE = language
46
-
47
-
48
39
  def get_current_internationalization_language() -> str:
49
40
  """Get the currently selected language from the session state."""
50
41
  if "internationalization_language" not in st.session_state:
@@ -73,7 +64,7 @@ def create_internationalization_language_selector() -> None:
73
64
  st.rerun()
74
65
 
75
66
 
76
- def translate(key: str, default: Optional[str] = None) -> str:
67
+ def translate_helper(key: str, default: Optional[str] = None, translations=None) -> str:
77
68
  """
78
69
  Translate a text key to the current language.
79
70
 
@@ -84,12 +75,28 @@ def translate(key: str, default: Optional[str] = None) -> str:
84
75
  Returns:
85
76
  The translated text in the current language
86
77
  """
78
+ if translations is None:
79
+ return key
87
80
  lang = get_current_internationalization_language()
88
81
 
89
- if key in TRANSLATIONS and lang in TRANSLATIONS[key]:
90
- return TRANSLATIONS[key][lang]
82
+ if key in translations and lang in translations[key]:
83
+ return translations[key][lang]
91
84
 
92
85
  # If the key doesn't exist, or the language is not available for this key
93
86
  if default:
94
87
  return default
95
88
  return key # Return the key itself as fallback
89
+
90
+
91
+ def translate(key: str, default: Optional[str] = None) -> str:
92
+ """
93
+ Translate a text key to the current language.
94
+
95
+ Args:
96
+ key: The translation key to look up
97
+ default: Default text to return if the key is not found
98
+
99
+ Returns:
100
+ The translated text in the current language
101
+ """
102
+ return translate_helper(key, default, TRANSLATIONS)
@@ -6,4 +6,4 @@
6
6
  #
7
7
 
8
8
  # Starts the Summarizer app (a comparison of various method of text summarization)
9
- CUDA_VISIBLE_DEVICES=0 OPENAI_API_KEY=$OPENAI_API_KEY OPENAI_BASE_URL=$OPENAI_BASE_URL OPENAI_DEFAULT_MODEL=$OPENAI_DEFAULT_MODEL streamlit run --theme.primaryColor royalblue summarization/summarizer_app.py
9
+ streamlit run --theme.primaryColor royalblue summarization/summarizer_app.py
@@ -0,0 +1,36 @@
1
+ #
2
+ # Copyright (c) 2024, RTE (https://www.rte-france.com)
3
+ # See AUTHORS.txt
4
+ # SPDX-License-Identifier: MPL-2.0
5
+ # This file is part of BERTrend.
6
+ #
7
+ # Use Python to load .env file and export variables
8
+ eval $(python3 << 'EOF'
9
+ from dotenv import dotenv_values
10
+ from dotenv import find_dotenv
11
+
12
+ # Find .env file starting from current directory
13
+ dotenv_path = find_dotenv(usecwd=True)
14
+
15
+ if dotenv_path:
16
+ # Load only the variables from .env file (not all environment)
17
+ env_vars = dotenv_values(dotenv_path)
18
+
19
+ # Export only the variables from .env
20
+ for key, value in env_vars.items():
21
+ if value is not None: # Skip empty values
22
+ # Escape special characters in the value
23
+ value_escaped = value.replace('"', '\\"')
24
+ print(f'export {key}="{value_escaped}"')
25
+ else:
26
+ import sys
27
+ print('echo "Warning: .env file not found"', file=sys.stderr)
28
+ EOF
29
+ )
30
+
31
+ # Set logs directory and create if not exists
32
+ export BERTREND_LOGS_DIR=$BERTREND_BASE_DIR/logs/bertrend
33
+ mkdir -p $BERTREND_LOGS_DIR
34
+
35
+ echo "Starting BERTrend Topic Analysis demo"
36
+ cd `pwd`/topic_analysis && CUDA_VISIBLE_DEVICES=0 streamlit run app.py 2>&1 | tee -a $BERTREND_LOGS_DIR/topic_analysis_demo.log
@@ -0,0 +1,36 @@
1
+ #
2
+ # Copyright (c) 2024, RTE (https://www.rte-france.com)
3
+ # See AUTHORS.txt
4
+ # SPDX-License-Identifier: MPL-2.0
5
+ # This file is part of BERTrend.
6
+ #
7
+ # Use Python to load .env file and export variables
8
+ eval $(python3 << 'EOF'
9
+ from dotenv import dotenv_values
10
+ from dotenv import find_dotenv
11
+
12
+ # Find .env file starting from current directory
13
+ dotenv_path = find_dotenv(usecwd=True)
14
+
15
+ if dotenv_path:
16
+ # Load only the variables from .env file (not all environment)
17
+ env_vars = dotenv_values(dotenv_path)
18
+
19
+ # Export only the variables from .env
20
+ for key, value in env_vars.items():
21
+ if value is not None: # Skip empty values
22
+ # Escape special characters in the value
23
+ value_escaped = value.replace('"', '\\"')
24
+ print(f'export {key}="{value_escaped}"')
25
+ else:
26
+ import sys
27
+ print('echo "Warning: .env file not found"', file=sys.stderr)
28
+ EOF
29
+ )
30
+
31
+ # Set logs directory and create if not exists
32
+ export BERTREND_LOGS_DIR=$BERTREND_BASE_DIR/logs/bertrend
33
+ mkdir -p $BERTREND_LOGS_DIR
34
+
35
+ echo "Starting BERTrend Weak Signal Analysis demo"
36
+ cd `pwd`/weak_signals && CUDA_VISIBLE_DEVICES=0 streamlit run app.py 2>&1 | tee -a $BERTREND_LOGS_DIR/weak_signals_demo.log
@@ -0,0 +1,52 @@
1
+ # Python
2
+ __pycache__
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ *.egg
11
+
12
+ # Virtual environments
13
+ venv/
14
+ env/
15
+ ENV/
16
+ .venv
17
+
18
+ # IDE
19
+ .vscode/
20
+ .idea/
21
+ *.swp
22
+ *.swo
23
+ *~
24
+
25
+ # OS
26
+ .DS_Store
27
+ Thumbs.db
28
+
29
+ # Project specific
30
+ *.sqlite
31
+ *.db
32
+ data/
33
+ logs/
34
+ *.log
35
+
36
+ # Git
37
+ .git/
38
+ .gitignore
39
+
40
+ # Docker
41
+ Dockerfile
42
+ docker-compose.yml
43
+ .dockerignore
44
+
45
+ # Documentation
46
+ README.md
47
+ *.md
48
+
49
+ # Tests
50
+ tests/
51
+ test_*.py
52
+ *_test.py
@@ -0,0 +1,310 @@
1
+ # Job Scheduler - Docker Setup
2
+
3
+ A FastAPI-based job scheduler with persistent SQLite storage and ProcessPoolExecutor, containerized with Docker.
4
+
5
+ ## 📁 Project Structure
6
+
7
+ ```
8
+ job-scheduler/
9
+ ├── main.py # FastAPI application
10
+ ├── requirements.txt # Python dependencies
11
+ ├── Dockerfile # Docker image definition
12
+ ├── docker-compose.yml # Docker Compose configuration
13
+ ├── .dockerignore # Docker ignore patterns
14
+ ├── data/ # SQLite database (persistent)
15
+ │ └── jobs.sqlite
16
+ └── logs/ # Application logs (optional)
17
+ ```
18
+
19
+ ## 🚀 Quick Start
20
+
21
+ ### 1. Build and Run
22
+
23
+ ```bash
24
+ # Build and start the container
25
+ docker-compose up -d
26
+
27
+ # View logs
28
+ docker-compose logs -f
29
+
30
+ # Check status
31
+ docker-compose ps
32
+ ```
33
+
34
+ ### 2. Access the API
35
+
36
+ - **API Base URL**: http://localhost:8000
37
+ - **API Documentation**: http://localhost:8000/docs
38
+ - **Health Check**: http://localhost:8000/
39
+
40
+ ### 3. Create Your First Job
41
+
42
+ ```bash
43
+ # Create a job that runs every minute
44
+ curl -X POST "http://localhost:8000/jobs" \
45
+ -H "Content-Type: application/json" \
46
+ -d '{
47
+ "job_id": "test_job",
48
+ "job_type": "interval",
49
+ "function_name": "sample_job",
50
+ "minutes": 1,
51
+ "kwargs": {"message": "Hello from Docker!"}
52
+ }'
53
+
54
+ # List all jobs
55
+ curl http://localhost:8000/jobs
56
+
57
+ # Check job details
58
+ curl http://localhost:8000/jobs/test_job
59
+ ```
60
+
61
+ ## 🛠️ Docker Commands
62
+
63
+ ### Basic Operations
64
+
65
+ ```bash
66
+ # Start services
67
+ docker-compose up -d
68
+
69
+ # Stop services
70
+ docker-compose down
71
+
72
+ # Restart services
73
+ docker-compose restart
74
+
75
+ # View logs
76
+ docker-compose logs -f scheduler
77
+
78
+ # Execute commands in container
79
+ docker-compose exec scheduler bash
80
+ ```
81
+
82
+ ### Database Management
83
+
84
+ ```bash
85
+ # Backup database
86
+ docker-compose exec scheduler cp /app/data/jobs.sqlite /app/data/jobs_backup.sqlite
87
+
88
+ # Access database
89
+ docker-compose exec scheduler sqlite3 /app/data/jobs.sqlite
90
+ ```
91
+
92
+ ### Rebuilding
93
+
94
+ ```bash
95
+ # Rebuild after code changes
96
+ docker-compose up -d --build
97
+
98
+ # Force rebuild
99
+ docker-compose build --no-cache
100
+ docker-compose up -d
101
+ ```
102
+
103
+ ## 📊 Monitoring
104
+
105
+ ### Health Check
106
+
107
+ The container includes automatic health checks:
108
+
109
+ ```bash
110
+ # Check container health
111
+ docker-compose ps
112
+
113
+ # Manual health check
114
+ curl http://localhost:8000/
115
+ ```
116
+
117
+ ### Logs
118
+
119
+ ```bash
120
+ # View real-time logs
121
+ docker-compose logs -f
122
+
123
+ # View last 100 lines
124
+ docker-compose logs --tail=100
125
+
126
+ # View logs from specific service
127
+ docker-compose logs scheduler
128
+ ```
129
+
130
+ ## 🔧 Configuration
131
+
132
+ ### Environment Variables
133
+
134
+ Edit `docker-compose.yml` to customize:
135
+
136
+ ```yaml
137
+ environment:
138
+ - TZ=Europe/Paris # Timezone
139
+ - LOG_LEVEL=INFO # Logging level
140
+ - MAX_WORKERS=5 # ProcessPoolExecutor workers
141
+ - DB_PATH=/app/data/jobs.sqlite
142
+ ```
143
+
144
+ ### Resource Limits
145
+
146
+ Adjust CPU and memory limits in `docker-compose.yml`:
147
+
148
+ ```yaml
149
+ deploy:
150
+ resources:
151
+ limits:
152
+ cpus: '2'
153
+ memory: 1G
154
+ ```
155
+
156
+ ### Port Mapping
157
+
158
+ Change the exposed port:
159
+
160
+ ```yaml
161
+ ports:
162
+ - "8080:8000" # Host:Container
163
+ ```
164
+
165
+ ## 💾 Data Persistence
166
+
167
+ The SQLite database is stored in `./data/jobs.sqlite` on your host machine, ensuring jobs persist across container restarts.
168
+
169
+ ### Backup Strategy
170
+
171
+ ```bash
172
+ # Manual backup
173
+ cp data/jobs.sqlite data/jobs_backup_$(date +%Y%m%d).sqlite
174
+
175
+ # Automated backup script
176
+ #!/bin/bash
177
+ docker-compose exec scheduler sqlite3 /app/data/jobs.sqlite ".backup '/app/data/backup_$(date +%Y%m%d_%H%M%S).sqlite'"
178
+ ```
179
+
180
+ ## 🔍 Troubleshooting
181
+
182
+ ### Container won't start
183
+
184
+ ```bash
185
+ # Check logs
186
+ docker-compose logs
187
+
188
+ # Rebuild
189
+ docker-compose down
190
+ docker-compose up -d --build
191
+ ```
192
+
193
+ ### Database locked
194
+
195
+ ```bash
196
+ # Stop all instances
197
+ docker-compose down
198
+
199
+ # Remove stale locks
200
+ rm data/jobs.sqlite-journal
201
+
202
+ # Restart
203
+ docker-compose up -d
204
+ ```
205
+
206
+ ### Permission issues
207
+
208
+ ```bash
209
+ # Fix permissions
210
+ sudo chown -R $USER:$USER data/
211
+ chmod -R 755 data/
212
+ ```
213
+
214
+ ## 🚢 Production Deployment
215
+
216
+ ### Using Docker Swarm
217
+
218
+ ```bash
219
+ # Initialize swarm
220
+ docker swarm init
221
+
222
+ # Deploy stack
223
+ docker stack deploy -c docker-compose.yml scheduler
224
+
225
+ # Check services
226
+ docker stack services scheduler
227
+ ```
228
+
229
+ ### Using Kubernetes
230
+
231
+ Create `deployment.yaml`:
232
+
233
+ ```yaml
234
+ apiVersion: apps/v1
235
+ kind: Deployment
236
+ metadata:
237
+ name: job-scheduler
238
+ spec:
239
+ replicas: 1
240
+ selector:
241
+ matchLabels:
242
+ app: scheduler
243
+ template:
244
+ metadata:
245
+ labels:
246
+ app: scheduler
247
+ spec:
248
+ containers:
249
+ - name: scheduler
250
+ image: job-scheduler:latest
251
+ ports:
252
+ - containerPort: 8000
253
+ volumeMounts:
254
+ - name: data
255
+ mountPath: /app/data
256
+ volumes:
257
+ - name: data
258
+ persistentVolumeClaim:
259
+ claimName: scheduler-data
260
+ ```
261
+
262
+ ## 📝 API Examples
263
+
264
+ ### Cron Job (Daily at 9 AM Paris time)
265
+
266
+ ```bash
267
+ curl -X POST "http://localhost:8000/jobs" \
268
+ -H "Content-Type: application/json" \
269
+ -d '{
270
+ "job_id": "daily_report",
271
+ "job_type": "cron",
272
+ "function_name": "report_generator",
273
+ "cron_expression": "0 9 * * *",
274
+ "kwargs": {"report_type": "daily"}
275
+ }'
276
+ ```
277
+
278
+ ### Validate Cron Expression
279
+
280
+ ```bash
281
+ curl -X POST "http://localhost:8000/cron/validate" \
282
+ -H "Content-Type: application/json" \
283
+ -d '{"expression": "*/15 * * * *"}'
284
+ ```
285
+
286
+ ### Get Cron Examples
287
+
288
+ ```bash
289
+ curl http://localhost:8000/cron/examples
290
+ ```
291
+
292
+ ## 🔐 Security Considerations
293
+
294
+ For production:
295
+
296
+ 1. **Add authentication**: Implement API key or OAuth
297
+ 2. **Use HTTPS**: Add reverse proxy (nginx/traefik)
298
+ 3. **Limit exposure**: Use internal networks
299
+ 4. **Regular backups**: Automated database backups
300
+ 5. **Update dependencies**: Keep packages current
301
+
302
+ ## 📚 Additional Resources
303
+
304
+ - [FastAPI Documentation](https://fastapi.tiangolo.com/)
305
+ - [APScheduler Documentation](https://apscheduler.readthedocs.io/)
306
+ - [Docker Documentation](https://docs.docker.com/)
307
+
308
+ ## 📄 License
309
+
310
+ This project is provided as-is for educational and commercial use.
@@ -0,0 +1,29 @@
1
+ FROM python:3.12-slim
2
+
3
+ # Set working directory
4
+ WORKDIR /app
5
+
6
+ # Set environment variables
7
+ ENV PYTHONUNBUFFERED=1 \
8
+ PYTHONDONTWRITEBYTECODE=1 \
9
+ PIP_NO_CACHE_DIR=1 \
10
+ PIP_DISABLE_PIP_VERSION_CHECK=1
11
+
12
+ # Copy requirements file
13
+ COPY requirements.txt .
14
+
15
+ # Install Python dependencies
16
+ RUN pip install --no-cache-dir -r requirements.txt
17
+
18
+ # Copy application code
19
+ COPY . /app/bertrend/services/scheduling
20
+
21
+ # Expose port
22
+ EXPOSE 8000
23
+
24
+ # Health check
25
+ HEALTHCHECK --interval=60s --timeout=10s --start-period=5s --retries=3 \
26
+ CMD python -c "import requests; requests.get('http://localhost:8000/')" || exit 1
27
+
28
+ # Run the application
29
+ CMD ["uvicorn", "bertrend.services.scheduling.scheduling_service:app", "--host", "0.0.0.0", "--port", "8000"]