local-deep-research 0.4.0__tar.gz → 0.4.2__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.
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/PKG-INFO +1 -1
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/pyproject.toml +1 -1
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/__init__.py +1 -0
- local_deep_research-0.4.2/src/local_deep_research/__version__.py +1 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/config/llm_config.py +1 -1
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/defaults/default_settings.json +1 -1
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/app.py +8 -1
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/services/research_service.py +15 -20
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/services/settings_manager.py +68 -17
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_searxng.py +1 -1
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/search_engine_factory.py +0 -2
- local_deep_research-0.4.2/tests/test_settings_manager.py +208 -0
- local_deep_research-0.4.0/src/local_deep_research/__version__.py +0 -1
- local_deep_research-0.4.0/src/local_deep_research/app.py +0 -8
- local_deep_research-0.4.0/tests/test_settings_manager.py +0 -98
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/LICENSE +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/README.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/filters/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/filters/base_filter.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/filters/cross_engine_filter.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/filters/journal_reputation_filter.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/findings/base_findings.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/findings/repository.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/knowledge/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/knowledge/base_knowledge.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/knowledge/standard_knowledge.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/questions/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/questions/base_question.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/questions/decomposition_question.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/questions/standard_question.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/repositories/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/strategies/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/strategies/base_strategy.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/strategies/iterdrag_strategy.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/strategies/parallel_search_strategy.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/strategies/rapid_search_strategy.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/strategies/source_based_strategy.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/strategies/standard_strategy.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/tools/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/tools/base_tool.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/tools/knowledge_tools/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/tools/question_tools/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/advanced_search_system/tools/search_tools/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/api/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/api/benchmark_functions.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/api/research_functions.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/README.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/benchmark_functions.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/cli/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/cli/benchmark_commands.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/cli.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/comparison/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/comparison/evaluator.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/datasets/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/datasets/base.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/datasets/browsecomp.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/datasets/custom_dataset_template.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/datasets/simpleqa.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/datasets/utils.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/datasets.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/efficiency/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/efficiency/resource_monitor.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/efficiency/speed_profiler.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/evaluators/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/evaluators/base.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/evaluators/browsecomp.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/evaluators/composite.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/evaluators/simpleqa.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/graders.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/metrics/README.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/metrics/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/metrics/calculation.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/metrics/reporting.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/metrics/visualization.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/metrics.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/optimization/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/optimization/api.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/optimization/metrics.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/optimization/optuna_optimizer.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/runners.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/benchmarks/templates.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/citation_handler.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/config/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/config/search_config.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/defaults/.env.template +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/defaults/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/migrate_db.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/report_generator.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/search_system.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/setup_data_dir.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/test_migration.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/db_utils.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/enums.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/es_utils.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/llm_utils.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/log_utils.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/search_utilities.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/setup_utils.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/utilities/url_utils.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/app_factory.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/database/README.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/database/migrate_to_ldr_db.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/database/migrations.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/database/models.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/database/schema_upgrade.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/models/database.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/models/settings.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/routes/api_routes.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/routes/benchmark_routes.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/routes/history_routes.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/routes/research_routes.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/routes/settings_routes.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/services/resource_service.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/services/settings_service.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/services/socket_service.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/css/custom_dropdown.css +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/css/settings.css +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/css/styles.css +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/custom_dropdown.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/detail.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/fallback/formatting.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/fallback/ui.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/history.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/logpanel.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/progress.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/research.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/results.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/settings.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/components/settings_sync.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/main.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/research_form.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/services/api.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/services/audio.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/services/formatting.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/services/pdf.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/services/socket.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/js/services/ui.js +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/sounds/README.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/sounds/error.mp3 +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/static/sounds/success.mp3 +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/base.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/components/custom_dropdown.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/components/log_panel.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/components/mobile_nav.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/components/settings_form.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/components/sidebar.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/pages/details.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/pages/history.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/pages/progress.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/pages/research.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/pages/results.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/templates/settings_dashboard.html +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/utils/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/utils/formatters.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web/utils/templates.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/default_search_engines.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/full_search.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/meta_search_engine.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_arxiv.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_brave.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_ddg.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_elasticsearch.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_github.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_google_pse.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_guardian.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_local.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_local_all.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_pubmed.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_semantic_scholar.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_serpapi.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_wayback.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/engines/search_engine_wikipedia.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/search_engine_base.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/web_search_engines/search_engines_config.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/TESTING_PROPOSAL.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/download_stuff_for_local_test.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/feature_tests/IMPLEMENTATION_GUIDE_241.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/feature_tests/README.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/feature_tests/__init__.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/feature_tests/test_custom_context.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/fix_tests/README.md +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/fix_tests/test_duplicate_links_fix.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/searxng/test_searxng_instance.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/searxng/test_searxng_integration.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/test_google_pse.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/test_url_utils.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/test_url_utils_debug.py +0 -0
- {local_deep_research-0.4.0 → local_deep_research-0.4.2}/tests/test_url_utils_simple.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: local-deep-research
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.2
|
4
4
|
Summary: AI-powered research assistant with deep, iterative analysis using LLMs and web searches
|
5
5
|
Author-Email: LearningCircuit <185559241+LearningCircuit@users.noreply.github.com>, HashedViking <6432677+HashedViking@users.noreply.github.com>
|
6
6
|
License: MIT License
|
@@ -9,6 +9,7 @@ from .__version__ import __version__
|
|
9
9
|
from .config.llm_config import get_llm
|
10
10
|
from .config.search_config import get_search
|
11
11
|
from .report_generator import get_report_generator
|
12
|
+
from .web.app import main
|
12
13
|
|
13
14
|
|
14
15
|
def get_advanced_search_system(strategy_name: str = "iterdrag"):
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.4.2"
|
{local_deep_research-0.4.0 → local_deep_research-0.4.2}/src/local_deep_research/config/llm_config.py
RENAMED
@@ -79,7 +79,7 @@ def get_llm(model_name=None, temperature=None, provider=None, openai_endpoint_ur
|
|
79
79
|
if get_db_setting("llm.supports_max_tokens", True):
|
80
80
|
# Use 80% of context window to leave room for prompts
|
81
81
|
max_tokens = min(
|
82
|
-
get_db_setting("llm.max_tokens", 30000), int(context_window_size * 0.8)
|
82
|
+
int(get_db_setting("llm.max_tokens", 30000)), int(context_window_size * 0.8)
|
83
83
|
)
|
84
84
|
common_params["max_tokens"] = max_tokens
|
85
85
|
|
@@ -94,7 +94,14 @@ def main():
|
|
94
94
|
debug = get_db_setting("web.debug", True)
|
95
95
|
|
96
96
|
logger.info(f"Starting web server on {host}:{port} (debug: {debug})")
|
97
|
-
socketio.run(
|
97
|
+
socketio.run(
|
98
|
+
app,
|
99
|
+
debug=debug,
|
100
|
+
host=host,
|
101
|
+
port=port,
|
102
|
+
allow_unsafe_werkzeug=True,
|
103
|
+
use_reloader=False,
|
104
|
+
)
|
98
105
|
|
99
106
|
|
100
107
|
if __name__ == "__main__":
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import hashlib
|
2
2
|
import json
|
3
|
-
import os
|
4
3
|
import threading
|
5
4
|
from datetime import datetime
|
5
|
+
from pathlib import Path
|
6
6
|
|
7
7
|
from loguru import logger
|
8
8
|
|
@@ -15,7 +15,7 @@ from ..models.database import add_log_to_db, calculate_duration, get_db_connecti
|
|
15
15
|
from .socket_service import emit_to_subscribers
|
16
16
|
|
17
17
|
# Output directory for research results
|
18
|
-
OUTPUT_DIR = "research_outputs"
|
18
|
+
OUTPUT_DIR = Path("research_outputs")
|
19
19
|
|
20
20
|
|
21
21
|
def start_research_process(
|
@@ -68,7 +68,7 @@ def start_research_process(
|
|
68
68
|
return thread
|
69
69
|
|
70
70
|
|
71
|
-
def _generate_report_path(query: str) ->
|
71
|
+
def _generate_report_path(query: str) -> Path:
|
72
72
|
"""
|
73
73
|
Generates a path for a new report file based on the query.
|
74
74
|
|
@@ -82,9 +82,8 @@ def _generate_report_path(query: str) -> str:
|
|
82
82
|
# Generate a unique filename that does not contain
|
83
83
|
# non-alphanumeric characters.
|
84
84
|
query_hash = hashlib.md5(query.encode("utf-8")).hexdigest()[:10]
|
85
|
-
return
|
86
|
-
|
87
|
-
f"research_report_{query_hash}_{datetime.now().isoformat()}.md",
|
85
|
+
return OUTPUT_DIR / (
|
86
|
+
f"research_report_{query_hash}_{int(datetime.now().timestamp())}.md"
|
88
87
|
)
|
89
88
|
|
90
89
|
|
@@ -139,8 +138,8 @@ def run_research_process(
|
|
139
138
|
)
|
140
139
|
|
141
140
|
# Set up the AI Context Manager
|
142
|
-
output_dir =
|
143
|
-
|
141
|
+
output_dir = OUTPUT_DIR / f"research_{research_id}"
|
142
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
144
143
|
|
145
144
|
# Set up progress callback
|
146
145
|
def progress_callback(message, progress_percent, metadata):
|
@@ -532,9 +531,7 @@ def run_research_process(
|
|
532
531
|
)
|
533
532
|
|
534
533
|
# Save as markdown file
|
535
|
-
|
536
|
-
os.makedirs(OUTPUT_DIR)
|
537
|
-
|
534
|
+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
538
535
|
report_path = _generate_report_path(query)
|
539
536
|
|
540
537
|
# Send progress update for writing to file
|
@@ -545,7 +542,7 @@ def run_research_process(
|
|
545
542
|
)
|
546
543
|
|
547
544
|
logger.info("Writing report to: %s", report_path)
|
548
|
-
with open(
|
545
|
+
with report_path.open("w", encoding="utf-8") as f:
|
549
546
|
f.write("# Quick Research Summary\n\n")
|
550
547
|
f.write(f"Query: {query}\n\n")
|
551
548
|
f.write(clean_markdown)
|
@@ -583,7 +580,7 @@ def run_research_process(
|
|
583
580
|
"completed",
|
584
581
|
completed_at,
|
585
582
|
duration_seconds,
|
586
|
-
report_path,
|
583
|
+
str(report_path),
|
587
584
|
json.dumps(metadata),
|
588
585
|
research_id,
|
589
586
|
),
|
@@ -598,7 +595,7 @@ def run_research_process(
|
|
598
595
|
progress_callback(
|
599
596
|
"Research completed successfully",
|
600
597
|
100,
|
601
|
-
{"phase": "complete", "report_path": report_path},
|
598
|
+
{"phase": "complete", "report_path": str(report_path)},
|
602
599
|
)
|
603
600
|
|
604
601
|
# Clean up resources
|
@@ -635,12 +632,10 @@ def run_research_process(
|
|
635
632
|
)
|
636
633
|
|
637
634
|
# Save as markdown file
|
638
|
-
|
639
|
-
os.makedirs(OUTPUT_DIR)
|
640
|
-
|
635
|
+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
641
636
|
report_path = _generate_report_path(query)
|
642
637
|
|
643
|
-
with open(
|
638
|
+
with report_path.open("w", encoding="utf-8") as f:
|
644
639
|
f.write(final_report["content"])
|
645
640
|
|
646
641
|
# Update database
|
@@ -668,7 +663,7 @@ def run_research_process(
|
|
668
663
|
"completed",
|
669
664
|
completed_at,
|
670
665
|
duration_seconds,
|
671
|
-
report_path,
|
666
|
+
str(report_path),
|
672
667
|
json.dumps(metadata),
|
673
668
|
research_id,
|
674
669
|
),
|
@@ -679,7 +674,7 @@ def run_research_process(
|
|
679
674
|
progress_callback(
|
680
675
|
"Research completed successfully",
|
681
676
|
100,
|
682
|
-
{"phase": "complete", "report_path": report_path},
|
677
|
+
{"phase": "complete", "report_path": str(report_path)},
|
683
678
|
)
|
684
679
|
|
685
680
|
# Clean up resources
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import importlib.resources as pkg_resources
|
2
2
|
import json
|
3
3
|
import os
|
4
|
-
from typing import Any, Dict, Optional, Union
|
4
|
+
from typing import Any, Dict, Optional, Type, Union
|
5
5
|
|
6
6
|
from loguru import logger
|
7
7
|
from sqlalchemy import func
|
@@ -45,6 +45,15 @@ class SettingsManager:
|
|
45
45
|
Provides methods to get and set settings, with the ability to override settings in memory.
|
46
46
|
"""
|
47
47
|
|
48
|
+
_UI_ELEMENT_TO_SETTING_TYPE = {
|
49
|
+
"text": str,
|
50
|
+
"password": str,
|
51
|
+
"select": str,
|
52
|
+
"number": float,
|
53
|
+
"range": float,
|
54
|
+
"checkbox": bool,
|
55
|
+
}
|
56
|
+
|
48
57
|
def __init__(self, db_session: Session):
|
49
58
|
"""
|
50
59
|
Initialize the settings manager
|
@@ -59,6 +68,57 @@ class SettingsManager:
|
|
59
68
|
default_settings = pkg_resources.read_text(defaults, "default_settings.json")
|
60
69
|
self.default_settings = json.loads(default_settings)
|
61
70
|
|
71
|
+
def __get_typed_setting_value(
|
72
|
+
self, setting: Type[Setting], default: Any = None, check_env: bool = True
|
73
|
+
) -> str | float | bool | None:
|
74
|
+
"""
|
75
|
+
Extracts the value for a particular setting, ensuring that it has the
|
76
|
+
correct type.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
setting: The setting to get the value for.
|
80
|
+
default: Default value to return if the value of the setting is
|
81
|
+
invalid.
|
82
|
+
check_env: If true, it will check the environment variable for
|
83
|
+
this setting before reading from the DB.
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
The value of the setting.
|
87
|
+
|
88
|
+
"""
|
89
|
+
setting_type = self._UI_ELEMENT_TO_SETTING_TYPE.get(setting.ui_element, None)
|
90
|
+
if setting_type is None:
|
91
|
+
logger.warning(
|
92
|
+
"Got unknown type {} for setting {}, returning default value.",
|
93
|
+
setting.ui_element,
|
94
|
+
setting.key,
|
95
|
+
)
|
96
|
+
return default
|
97
|
+
|
98
|
+
# Check environment variable first, then database.
|
99
|
+
if check_env:
|
100
|
+
env_value = check_env_setting(setting.key)
|
101
|
+
if env_value is not None:
|
102
|
+
try:
|
103
|
+
return setting_type(env_value)
|
104
|
+
except ValueError:
|
105
|
+
logger.warning(
|
106
|
+
"Setting {} has invalid value {}. Falling back to DB.",
|
107
|
+
setting.key,
|
108
|
+
env_value,
|
109
|
+
)
|
110
|
+
|
111
|
+
# If environment variable does not exist, read from the database.
|
112
|
+
try:
|
113
|
+
return setting_type(setting.value)
|
114
|
+
except ValueError:
|
115
|
+
logger.warning(
|
116
|
+
"Setting {} has invalid value {}. Returning default.",
|
117
|
+
setting.key,
|
118
|
+
setting.value,
|
119
|
+
)
|
120
|
+
return default
|
121
|
+
|
62
122
|
def get_setting(self, key: str, default: Any = None, check_env: bool = True) -> Any:
|
63
123
|
"""
|
64
124
|
Get a setting value
|
@@ -72,11 +132,6 @@ class SettingsManager:
|
|
72
132
|
Returns:
|
73
133
|
Setting value or default if not found
|
74
134
|
"""
|
75
|
-
if check_env:
|
76
|
-
env_value = check_env_setting(key)
|
77
|
-
if env_value is not None:
|
78
|
-
return env_value
|
79
|
-
|
80
135
|
# If using database first approach and session available, check database
|
81
136
|
if self.db_first and self.db_session:
|
82
137
|
try:
|
@@ -87,22 +142,17 @@ class SettingsManager:
|
|
87
142
|
)
|
88
143
|
if len(settings) == 1:
|
89
144
|
# This is a bottom-level key.
|
90
|
-
|
91
|
-
|
145
|
+
return self.__get_typed_setting_value(
|
146
|
+
settings[0], default, check_env
|
147
|
+
)
|
92
148
|
elif len(settings) > 1:
|
93
149
|
# This is a higher-level key.
|
94
150
|
settings_map = {}
|
95
151
|
for setting in settings:
|
96
152
|
output_key = setting.key.removeprefix(f"{key}.")
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
# Handle possible replacements from environment variables.
|
101
|
-
env_value = check_env_setting(setting.key)
|
102
|
-
if env_value is not None:
|
103
|
-
value = env_value
|
104
|
-
|
105
|
-
settings_map[output_key] = value
|
153
|
+
settings_map[output_key] = self.__get_typed_setting_value(
|
154
|
+
setting, default, check_env
|
155
|
+
)
|
106
156
|
return settings_map
|
107
157
|
except SQLAlchemyError as e:
|
108
158
|
logger.error(f"Error retrieving setting {key} from database: {e}")
|
@@ -149,6 +199,7 @@ class SettingsManager:
|
|
149
199
|
value=value,
|
150
200
|
type=setting_type,
|
151
201
|
name=key.split(".")[-1].replace("_", " ").title(),
|
202
|
+
ui_element="text",
|
152
203
|
description=f"Setting for {key}",
|
153
204
|
)
|
154
205
|
self.db_session.add(new_setting)
|
@@ -98,7 +98,7 @@ class SearXNGSearchEngine(BaseSearchEngine):
|
|
98
98
|
self.language = language
|
99
99
|
try:
|
100
100
|
self.safe_search = SafeSearchSetting[safe_search]
|
101
|
-
except
|
101
|
+
except KeyError:
|
102
102
|
logger.error(
|
103
103
|
"'{}' is not a valid safe search setting. Disabling safe search",
|
104
104
|
safe_search,
|
@@ -49,8 +49,6 @@ def create_search_engine(
|
|
49
49
|
|
50
50
|
# If not found, check the database for the API key
|
51
51
|
if not api_key:
|
52
|
-
from ..utilities.db_utils import get_db_setting
|
53
|
-
|
54
52
|
api_key = get_db_setting(f"search.engine.web.{engine_name}.api_key")
|
55
53
|
|
56
54
|
# Still try to get from engine config if not found
|
@@ -0,0 +1,208 @@
|
|
1
|
+
import os
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
from sqlalchemy.exc import SQLAlchemyError
|
6
|
+
|
7
|
+
from src.local_deep_research.web.services.settings_manager import (
|
8
|
+
Setting,
|
9
|
+
SettingsManager,
|
10
|
+
SettingType,
|
11
|
+
check_env_setting,
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
def test_check_env_setting_exists(monkeypatch):
|
16
|
+
monkeypatch.setenv("LDR_APP_VERSION", "1.0.0")
|
17
|
+
assert check_env_setting("app.version") == "1.0.0"
|
18
|
+
|
19
|
+
|
20
|
+
def test_check_env_setting_not_exists():
|
21
|
+
# Ensure the environment variable is not set
|
22
|
+
if "LDR_APP_VERSION" in os.environ:
|
23
|
+
del os.environ["LDR_APP_VERSION"]
|
24
|
+
assert check_env_setting("app.version") is None
|
25
|
+
|
26
|
+
|
27
|
+
@pytest.mark.parametrize(
|
28
|
+
"ui_element, setting_value, expected",
|
29
|
+
[
|
30
|
+
("text", "hello", "hello"),
|
31
|
+
("select", "option_a", "option_a"),
|
32
|
+
("password", "secret", "secret"),
|
33
|
+
("number", "3.14", 3.14),
|
34
|
+
("range", "3.14", 3.14),
|
35
|
+
("checkbox", "true", True),
|
36
|
+
],
|
37
|
+
)
|
38
|
+
def test_get_setting_from_db(
|
39
|
+
mocker, ui_element: str, setting_value: str, expected: Any
|
40
|
+
):
|
41
|
+
"""
|
42
|
+
Tests that we can successfully read settings from the DB.
|
43
|
+
|
44
|
+
Args:
|
45
|
+
mocker: The fixture to use for mocking.
|
46
|
+
ui_element: The value of the `ui_element` parameter, which controls the return type.
|
47
|
+
setting_value: The value to use for the setting in the DB.
|
48
|
+
expected: The expected typed value of the setting.
|
49
|
+
"""
|
50
|
+
# Arrange: Set up the mock database session and a sample setting
|
51
|
+
mock_db_session = mocker.MagicMock()
|
52
|
+
mock_setting = Setting(
|
53
|
+
key="test.setting", value=setting_value, ui_element=ui_element
|
54
|
+
)
|
55
|
+
mock_db_session.query.return_value.filter.return_value.all.return_value = [
|
56
|
+
mock_setting
|
57
|
+
]
|
58
|
+
|
59
|
+
# Act: Call the get_setting method with the test key
|
60
|
+
settings_manager = SettingsManager(db_session=mock_db_session)
|
61
|
+
result = settings_manager.get_setting("test.setting")
|
62
|
+
|
63
|
+
# Assert: Verify that the result matches the expected value
|
64
|
+
assert result == expected, f"Expected {expected}, but got {result}"
|
65
|
+
|
66
|
+
|
67
|
+
@pytest.mark.parametrize(
|
68
|
+
"ui_element, env_value, expected",
|
69
|
+
[
|
70
|
+
("text", "hello", "hello"),
|
71
|
+
("select", "option_a", "option_a"),
|
72
|
+
("password", "secret", "secret"),
|
73
|
+
("number", "3.14", 3.14),
|
74
|
+
("range", "3.14", 3.14),
|
75
|
+
("checkbox", "true", True),
|
76
|
+
],
|
77
|
+
)
|
78
|
+
def test_get_setting_from_env(
|
79
|
+
mocker, monkeypatch, ui_element: str, env_value: str, expected: Any
|
80
|
+
):
|
81
|
+
"""
|
82
|
+
Tests that we can successfully override DB settings with environment
|
83
|
+
variables.
|
84
|
+
|
85
|
+
Args:
|
86
|
+
mocker: The fixture to use for mocking.
|
87
|
+
ui_element: The value of the `ui_element` parameter, which controls the return type.
|
88
|
+
env_value: The value to use for the setting in the environment variable.
|
89
|
+
expected: The expected typed value of the setting.
|
90
|
+
"""
|
91
|
+
# Arrange: Set up the mock database session and ensure an environment variable is set
|
92
|
+
mock_db_session = mocker.MagicMock()
|
93
|
+
monkeypatch.setenv("LDR_TEST_SETTING", env_value)
|
94
|
+
# Ensure DB query returns an old version to verify environment variable is prioritized
|
95
|
+
mock_setting = Setting(key="test.setting", value="db_value", ui_element=ui_element)
|
96
|
+
mock_db_session.query.return_value.filter.return_value.all.return_value = [
|
97
|
+
mock_setting
|
98
|
+
]
|
99
|
+
|
100
|
+
# Act: Call the get_setting method with the test key
|
101
|
+
settings_manager = SettingsManager(db_session=mock_db_session)
|
102
|
+
result = settings_manager.get_setting("test.setting")
|
103
|
+
|
104
|
+
# Assert: Verify that the result matches the expected value
|
105
|
+
assert result == expected, f"Expected {expected}, but got {result}"
|
106
|
+
|
107
|
+
|
108
|
+
def test_get_setting_default(mocker):
|
109
|
+
mock_db_session = mocker.MagicMock()
|
110
|
+
# Ensure DB query returns nothing
|
111
|
+
mock_db_session.query.return_value.filter.return_value.all.return_value = []
|
112
|
+
|
113
|
+
settings_manager = SettingsManager(db_session=mock_db_session)
|
114
|
+
assert (
|
115
|
+
settings_manager.get_setting("non_existent_setting", default="default_value")
|
116
|
+
== "default_value"
|
117
|
+
)
|
118
|
+
|
119
|
+
|
120
|
+
def test_get_setting_invalid_type(mocker):
|
121
|
+
"""
|
122
|
+
Tests that when a setting's value cannot be converted to the type
|
123
|
+
specified by the `ui_element`, it will always return the default value.
|
124
|
+
|
125
|
+
Args:
|
126
|
+
mocker: The fixture to use for mocking.
|
127
|
+
|
128
|
+
"""
|
129
|
+
# Arrange: Set up a mock DB session and setting with an invalid type
|
130
|
+
mock_db_session = mocker.MagicMock()
|
131
|
+
mock_setting = Setting(
|
132
|
+
key="test.invalid_type", value="not_a_number", ui_element="number"
|
133
|
+
)
|
134
|
+
mock_db_session.query.return_value.filter.return_value.all.return_value = [
|
135
|
+
mock_setting
|
136
|
+
]
|
137
|
+
|
138
|
+
# Act: Call get_setting with a default value and an invalid type
|
139
|
+
settings_manager = SettingsManager(db_session=mock_db_session)
|
140
|
+
result = settings_manager.get_setting("test.invalid_type", default=10)
|
141
|
+
|
142
|
+
# Assert: Check that the default value is returned and not the invalid string
|
143
|
+
assert result == 10
|
144
|
+
|
145
|
+
|
146
|
+
# The mocker fixture is automatically available
|
147
|
+
def test_set_setting_update_existing(mocker):
|
148
|
+
mock_db_session = mocker.MagicMock()
|
149
|
+
mock_setting = Setting(key="app.version", value="1.0.0")
|
150
|
+
mock_db_session.query.return_value.filter.return_value.first.return_value = (
|
151
|
+
mock_setting
|
152
|
+
)
|
153
|
+
mocker.patch(
|
154
|
+
"src.local_deep_research.web.services.settings_manager.func.now"
|
155
|
+
) # Patching the func.now call
|
156
|
+
|
157
|
+
settings_manager = SettingsManager(db_session=mock_db_session)
|
158
|
+
result = settings_manager.set_setting("app.version", "2.0.0")
|
159
|
+
|
160
|
+
assert result is True
|
161
|
+
assert mock_setting.value == "2.0.0"
|
162
|
+
mock_db_session.commit.assert_called_once()
|
163
|
+
mock_db_session.rollback.assert_not_called()
|
164
|
+
|
165
|
+
|
166
|
+
def test_set_setting_create_new(mocker):
|
167
|
+
mock_db_session = mocker.MagicMock()
|
168
|
+
mock_db_session.query.return_value.filter.return_value.first.return_value = None
|
169
|
+
mocker.patch(
|
170
|
+
"src.local_deep_research.web.services.settings_manager.func.now"
|
171
|
+
) # Patching the func.now call
|
172
|
+
|
173
|
+
settings_manager = SettingsManager(db_session=mock_db_session)
|
174
|
+
result = settings_manager.set_setting("new.setting", "new_value")
|
175
|
+
|
176
|
+
assert result is True
|
177
|
+
mock_db_session.add.assert_called_once()
|
178
|
+
new_setting = mock_db_session.add.call_args[0][0]
|
179
|
+
assert isinstance(new_setting, Setting)
|
180
|
+
assert new_setting.key == "new.setting"
|
181
|
+
assert new_setting.value == "new_value"
|
182
|
+
assert new_setting.type == SettingType.APP # Assuming 'app' type for this key
|
183
|
+
mock_db_session.commit.assert_called_once()
|
184
|
+
mock_db_session.rollback.assert_not_called()
|
185
|
+
|
186
|
+
|
187
|
+
def test_set_setting_db_error(mocker):
|
188
|
+
mock_db_session = mocker.MagicMock()
|
189
|
+
# Set the side_effect to an instance of SQLAlchemyError
|
190
|
+
mock_db_session.query.return_value.filter.return_value.first.side_effect = (
|
191
|
+
SQLAlchemyError("Simulated DB Error")
|
192
|
+
)
|
193
|
+
|
194
|
+
# Mock the logger to check if error is logged
|
195
|
+
mock_logger = mocker.patch(
|
196
|
+
"src.local_deep_research.web.services.settings_manager.logger"
|
197
|
+
)
|
198
|
+
|
199
|
+
settings_manager = SettingsManager(db_session=mock_db_session)
|
200
|
+
result = settings_manager.set_setting("app.version", "2.0.0")
|
201
|
+
|
202
|
+
# Assert that the method returned False
|
203
|
+
assert result is False
|
204
|
+
|
205
|
+
mock_db_session.rollback.assert_called_once()
|
206
|
+
mock_db_session.commit.assert_not_called()
|
207
|
+
mock_logger.error.assert_called_once()
|
208
|
+
# mock_logger.error.assert_called_once_with("Error setting value for app.version: Simulated DB Error")
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.4.0"
|
@@ -1,98 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import pytest
|
3
|
-
import sys
|
4
|
-
from pathlib import Path
|
5
|
-
from sqlalchemy.exc import SQLAlchemyError
|
6
|
-
|
7
|
-
# Add the src directory to the path before importing project modules
|
8
|
-
sys.path.append(str(Path(__file__).parent.parent))
|
9
|
-
|
10
|
-
from src.local_deep_research.web.services.settings_manager import check_env_setting, SettingsManager, Setting, SettingType
|
11
|
-
|
12
|
-
def test_check_env_setting_exists(monkeypatch):
|
13
|
-
monkeypatch.setenv("LDR_APP_VERSION", "1.0.0")
|
14
|
-
assert check_env_setting("app.version") == "1.0.0"
|
15
|
-
|
16
|
-
def test_check_env_setting_not_exists():
|
17
|
-
# Ensure the environment variable is not set
|
18
|
-
if "LDR_APP_VERSION" in os.environ:
|
19
|
-
del os.environ["LDR_APP_VERSION"]
|
20
|
-
assert check_env_setting("app.version") is None
|
21
|
-
|
22
|
-
def test_get_setting_from_db(mocker):
|
23
|
-
mock_db_session = mocker.MagicMock()
|
24
|
-
mock_setting = Setting(key="app.version", value="1.0.0")
|
25
|
-
# Use mocker.patch.object for patching instances
|
26
|
-
mock_db_session.query.return_value.filter.return_value.all.return_value = [mock_setting]
|
27
|
-
|
28
|
-
settings_manager = SettingsManager(db_session=mock_db_session)
|
29
|
-
assert settings_manager.get_setting("app.version") == "1.0.0"
|
30
|
-
|
31
|
-
def test_get_setting_from_env(mocker, monkeypatch):
|
32
|
-
mock_db_session = mocker.MagicMock()
|
33
|
-
monkeypatch.setenv("LDR_APP_VERSION", "2.0.0")
|
34
|
-
# Ensure DB query returns nothing to verify environment variable is prioritized
|
35
|
-
mock_db_session.query.return_value.filter.return_value.all.return_value = []
|
36
|
-
|
37
|
-
settings_manager = SettingsManager(db_session=mock_db_session)
|
38
|
-
assert settings_manager.get_setting("app.version") == "2.0.0"
|
39
|
-
|
40
|
-
def test_get_setting_default(mocker):
|
41
|
-
mock_db_session = mocker.MagicMock()
|
42
|
-
# Ensure DB query returns nothing
|
43
|
-
mock_db_session.query.return_value.filter.return_value.all.return_value = []
|
44
|
-
|
45
|
-
settings_manager = SettingsManager(db_session=mock_db_session)
|
46
|
-
assert settings_manager.get_setting("non_existent_setting", default="default_value") == "default_value"
|
47
|
-
|
48
|
-
# The mocker fixture is automatically available
|
49
|
-
def test_set_setting_update_existing(mocker):
|
50
|
-
mock_db_session = mocker.MagicMock()
|
51
|
-
mock_setting = Setting(key="app.version", value="1.0.0")
|
52
|
-
mock_db_session.query.return_value.filter.return_value.first.return_value = mock_setting
|
53
|
-
mocker.patch("src.local_deep_research.web.services.settings_manager.func.now") # Patching the func.now call
|
54
|
-
|
55
|
-
settings_manager = SettingsManager(db_session=mock_db_session)
|
56
|
-
result = settings_manager.set_setting("app.version", "2.0.0")
|
57
|
-
|
58
|
-
assert result is True
|
59
|
-
assert mock_setting.value == "2.0.0"
|
60
|
-
mock_db_session.commit.assert_called_once()
|
61
|
-
mock_db_session.rollback.assert_not_called()
|
62
|
-
|
63
|
-
def test_set_setting_create_new(mocker):
|
64
|
-
mock_db_session = mocker.MagicMock()
|
65
|
-
mock_db_session.query.return_value.filter.return_value.first.return_value = None
|
66
|
-
mocker.patch("src.local_deep_research.web.services.settings_manager.func.now") # Patching the func.now call
|
67
|
-
|
68
|
-
settings_manager = SettingsManager(db_session=mock_db_session)
|
69
|
-
result = settings_manager.set_setting("new.setting", "new_value")
|
70
|
-
|
71
|
-
assert result is True
|
72
|
-
mock_db_session.add.assert_called_once()
|
73
|
-
new_setting = mock_db_session.add.call_args[0][0]
|
74
|
-
assert isinstance(new_setting, Setting)
|
75
|
-
assert new_setting.key == "new.setting"
|
76
|
-
assert new_setting.value == "new_value"
|
77
|
-
assert new_setting.type == SettingType.APP # Assuming 'app' type for this key
|
78
|
-
mock_db_session.commit.assert_called_once()
|
79
|
-
mock_db_session.rollback.assert_not_called()
|
80
|
-
|
81
|
-
def test_set_setting_db_error(mocker):
|
82
|
-
mock_db_session = mocker.MagicMock()
|
83
|
-
# Set the side_effect to an instance of SQLAlchemyError
|
84
|
-
mock_db_session.query.return_value.filter.return_value.first.side_effect = SQLAlchemyError("Simulated DB Error")
|
85
|
-
|
86
|
-
# Mock the logger to check if error is logged
|
87
|
-
mock_logger = mocker.patch("src.local_deep_research.web.services.settings_manager.logger")
|
88
|
-
|
89
|
-
settings_manager = SettingsManager(db_session=mock_db_session)
|
90
|
-
result = settings_manager.set_setting("app.version", "2.0.0")
|
91
|
-
|
92
|
-
# Assert that the method returned False
|
93
|
-
assert result is False
|
94
|
-
|
95
|
-
mock_db_session.rollback.assert_called_once()
|
96
|
-
mock_db_session.commit.assert_not_called()
|
97
|
-
mock_logger.error.assert_called_once()
|
98
|
-
# mock_logger.error.assert_called_once_with("Error setting value for app.version: Simulated DB Error")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|