attune-ai 2.0.0__py3-none-any.whl
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.
- attune/__init__.py +358 -0
- attune/adaptive/__init__.py +13 -0
- attune/adaptive/task_complexity.py +127 -0
- attune/agent_monitoring.py +414 -0
- attune/cache/__init__.py +117 -0
- attune/cache/base.py +166 -0
- attune/cache/dependency_manager.py +256 -0
- attune/cache/hash_only.py +251 -0
- attune/cache/hybrid.py +457 -0
- attune/cache/storage.py +285 -0
- attune/cache_monitor.py +356 -0
- attune/cache_stats.py +298 -0
- attune/cli/__init__.py +152 -0
- attune/cli/__main__.py +12 -0
- attune/cli/commands/__init__.py +1 -0
- attune/cli/commands/batch.py +264 -0
- attune/cli/commands/cache.py +248 -0
- attune/cli/commands/help.py +331 -0
- attune/cli/commands/info.py +140 -0
- attune/cli/commands/inspect.py +436 -0
- attune/cli/commands/inspection.py +57 -0
- attune/cli/commands/memory.py +48 -0
- attune/cli/commands/metrics.py +92 -0
- attune/cli/commands/orchestrate.py +184 -0
- attune/cli/commands/patterns.py +207 -0
- attune/cli/commands/profiling.py +202 -0
- attune/cli/commands/provider.py +98 -0
- attune/cli/commands/routing.py +285 -0
- attune/cli/commands/setup.py +96 -0
- attune/cli/commands/status.py +235 -0
- attune/cli/commands/sync.py +166 -0
- attune/cli/commands/tier.py +121 -0
- attune/cli/commands/utilities.py +114 -0
- attune/cli/commands/workflow.py +579 -0
- attune/cli/core.py +32 -0
- attune/cli/parsers/__init__.py +68 -0
- attune/cli/parsers/batch.py +118 -0
- attune/cli/parsers/cache.py +65 -0
- attune/cli/parsers/help.py +41 -0
- attune/cli/parsers/info.py +26 -0
- attune/cli/parsers/inspect.py +66 -0
- attune/cli/parsers/metrics.py +42 -0
- attune/cli/parsers/orchestrate.py +61 -0
- attune/cli/parsers/patterns.py +54 -0
- attune/cli/parsers/provider.py +40 -0
- attune/cli/parsers/routing.py +110 -0
- attune/cli/parsers/setup.py +42 -0
- attune/cli/parsers/status.py +47 -0
- attune/cli/parsers/sync.py +31 -0
- attune/cli/parsers/tier.py +33 -0
- attune/cli/parsers/workflow.py +77 -0
- attune/cli/utils/__init__.py +1 -0
- attune/cli/utils/data.py +242 -0
- attune/cli/utils/helpers.py +68 -0
- attune/cli_legacy.py +3957 -0
- attune/cli_minimal.py +1159 -0
- attune/cli_router.py +437 -0
- attune/cli_unified.py +814 -0
- attune/config/__init__.py +66 -0
- attune/config/xml_config.py +286 -0
- attune/config.py +545 -0
- attune/coordination.py +870 -0
- attune/core.py +1511 -0
- attune/core_modules/__init__.py +15 -0
- attune/cost_tracker.py +626 -0
- attune/dashboard/__init__.py +41 -0
- attune/dashboard/app.py +512 -0
- attune/dashboard/simple_server.py +435 -0
- attune/dashboard/standalone_server.py +547 -0
- attune/discovery.py +306 -0
- attune/emergence.py +306 -0
- attune/exceptions.py +123 -0
- attune/feedback_loops.py +373 -0
- attune/hot_reload/README.md +473 -0
- attune/hot_reload/__init__.py +62 -0
- attune/hot_reload/config.py +83 -0
- attune/hot_reload/integration.py +229 -0
- attune/hot_reload/reloader.py +298 -0
- attune/hot_reload/watcher.py +183 -0
- attune/hot_reload/websocket.py +177 -0
- attune/levels.py +577 -0
- attune/leverage_points.py +441 -0
- attune/logging_config.py +261 -0
- attune/mcp/__init__.py +10 -0
- attune/mcp/server.py +506 -0
- attune/memory/__init__.py +237 -0
- attune/memory/claude_memory.py +469 -0
- attune/memory/config.py +224 -0
- attune/memory/control_panel.py +1290 -0
- attune/memory/control_panel_support.py +145 -0
- attune/memory/cross_session.py +845 -0
- attune/memory/edges.py +179 -0
- attune/memory/encryption.py +159 -0
- attune/memory/file_session.py +770 -0
- attune/memory/graph.py +570 -0
- attune/memory/long_term.py +913 -0
- attune/memory/long_term_types.py +99 -0
- attune/memory/mixins/__init__.py +25 -0
- attune/memory/mixins/backend_init_mixin.py +249 -0
- attune/memory/mixins/capabilities_mixin.py +208 -0
- attune/memory/mixins/handoff_mixin.py +208 -0
- attune/memory/mixins/lifecycle_mixin.py +49 -0
- attune/memory/mixins/long_term_mixin.py +352 -0
- attune/memory/mixins/promotion_mixin.py +109 -0
- attune/memory/mixins/short_term_mixin.py +182 -0
- attune/memory/nodes.py +179 -0
- attune/memory/redis_bootstrap.py +540 -0
- attune/memory/security/__init__.py +31 -0
- attune/memory/security/audit_logger.py +932 -0
- attune/memory/security/pii_scrubber.py +640 -0
- attune/memory/security/secrets_detector.py +678 -0
- attune/memory/short_term.py +2192 -0
- attune/memory/simple_storage.py +302 -0
- attune/memory/storage/__init__.py +15 -0
- attune/memory/storage_backend.py +167 -0
- attune/memory/summary_index.py +583 -0
- attune/memory/types.py +446 -0
- attune/memory/unified.py +182 -0
- attune/meta_workflows/__init__.py +74 -0
- attune/meta_workflows/agent_creator.py +248 -0
- attune/meta_workflows/builtin_templates.py +567 -0
- attune/meta_workflows/cli_commands/__init__.py +56 -0
- attune/meta_workflows/cli_commands/agent_commands.py +321 -0
- attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
- attune/meta_workflows/cli_commands/config_commands.py +232 -0
- attune/meta_workflows/cli_commands/memory_commands.py +182 -0
- attune/meta_workflows/cli_commands/template_commands.py +354 -0
- attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
- attune/meta_workflows/cli_meta_workflows.py +59 -0
- attune/meta_workflows/form_engine.py +292 -0
- attune/meta_workflows/intent_detector.py +409 -0
- attune/meta_workflows/models.py +569 -0
- attune/meta_workflows/pattern_learner.py +738 -0
- attune/meta_workflows/plan_generator.py +384 -0
- attune/meta_workflows/session_context.py +397 -0
- attune/meta_workflows/template_registry.py +229 -0
- attune/meta_workflows/workflow.py +984 -0
- attune/metrics/__init__.py +12 -0
- attune/metrics/collector.py +31 -0
- attune/metrics/prompt_metrics.py +194 -0
- attune/models/__init__.py +172 -0
- attune/models/__main__.py +13 -0
- attune/models/adaptive_routing.py +437 -0
- attune/models/auth_cli.py +444 -0
- attune/models/auth_strategy.py +450 -0
- attune/models/cli.py +655 -0
- attune/models/empathy_executor.py +354 -0
- attune/models/executor.py +257 -0
- attune/models/fallback.py +762 -0
- attune/models/provider_config.py +282 -0
- attune/models/registry.py +472 -0
- attune/models/tasks.py +359 -0
- attune/models/telemetry/__init__.py +71 -0
- attune/models/telemetry/analytics.py +594 -0
- attune/models/telemetry/backend.py +196 -0
- attune/models/telemetry/data_models.py +431 -0
- attune/models/telemetry/storage.py +489 -0
- attune/models/token_estimator.py +420 -0
- attune/models/validation.py +280 -0
- attune/monitoring/__init__.py +52 -0
- attune/monitoring/alerts.py +946 -0
- attune/monitoring/alerts_cli.py +448 -0
- attune/monitoring/multi_backend.py +271 -0
- attune/monitoring/otel_backend.py +362 -0
- attune/optimization/__init__.py +19 -0
- attune/optimization/context_optimizer.py +272 -0
- attune/orchestration/__init__.py +67 -0
- attune/orchestration/agent_templates.py +707 -0
- attune/orchestration/config_store.py +499 -0
- attune/orchestration/execution_strategies.py +2111 -0
- attune/orchestration/meta_orchestrator.py +1168 -0
- attune/orchestration/pattern_learner.py +696 -0
- attune/orchestration/real_tools.py +931 -0
- attune/pattern_cache.py +187 -0
- attune/pattern_library.py +542 -0
- attune/patterns/debugging/all_patterns.json +81 -0
- attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
- attune/patterns/refactoring_memory.json +89 -0
- attune/persistence.py +564 -0
- attune/platform_utils.py +265 -0
- attune/plugins/__init__.py +28 -0
- attune/plugins/base.py +361 -0
- attune/plugins/registry.py +268 -0
- attune/project_index/__init__.py +32 -0
- attune/project_index/cli.py +335 -0
- attune/project_index/index.py +667 -0
- attune/project_index/models.py +504 -0
- attune/project_index/reports.py +474 -0
- attune/project_index/scanner.py +777 -0
- attune/project_index/scanner_parallel.py +291 -0
- attune/prompts/__init__.py +61 -0
- attune/prompts/config.py +77 -0
- attune/prompts/context.py +177 -0
- attune/prompts/parser.py +285 -0
- attune/prompts/registry.py +313 -0
- attune/prompts/templates.py +208 -0
- attune/redis_config.py +302 -0
- attune/redis_memory.py +799 -0
- attune/resilience/__init__.py +56 -0
- attune/resilience/circuit_breaker.py +256 -0
- attune/resilience/fallback.py +179 -0
- attune/resilience/health.py +300 -0
- attune/resilience/retry.py +209 -0
- attune/resilience/timeout.py +135 -0
- attune/routing/__init__.py +43 -0
- attune/routing/chain_executor.py +433 -0
- attune/routing/classifier.py +217 -0
- attune/routing/smart_router.py +234 -0
- attune/routing/workflow_registry.py +343 -0
- attune/scaffolding/README.md +589 -0
- attune/scaffolding/__init__.py +35 -0
- attune/scaffolding/__main__.py +14 -0
- attune/scaffolding/cli.py +240 -0
- attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
- attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
- attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
- attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
- attune/socratic/__init__.py +256 -0
- attune/socratic/ab_testing.py +958 -0
- attune/socratic/blueprint.py +533 -0
- attune/socratic/cli.py +703 -0
- attune/socratic/collaboration.py +1114 -0
- attune/socratic/domain_templates.py +924 -0
- attune/socratic/embeddings.py +738 -0
- attune/socratic/engine.py +794 -0
- attune/socratic/explainer.py +682 -0
- attune/socratic/feedback.py +772 -0
- attune/socratic/forms.py +629 -0
- attune/socratic/generator.py +732 -0
- attune/socratic/llm_analyzer.py +637 -0
- attune/socratic/mcp_server.py +702 -0
- attune/socratic/session.py +312 -0
- attune/socratic/storage.py +667 -0
- attune/socratic/success.py +730 -0
- attune/socratic/visual_editor.py +860 -0
- attune/socratic/web_ui.py +958 -0
- attune/telemetry/__init__.py +39 -0
- attune/telemetry/agent_coordination.py +475 -0
- attune/telemetry/agent_tracking.py +367 -0
- attune/telemetry/approval_gates.py +545 -0
- attune/telemetry/cli.py +1231 -0
- attune/telemetry/commands/__init__.py +14 -0
- attune/telemetry/commands/dashboard_commands.py +696 -0
- attune/telemetry/event_streaming.py +409 -0
- attune/telemetry/feedback_loop.py +567 -0
- attune/telemetry/usage_tracker.py +591 -0
- attune/templates.py +754 -0
- attune/test_generator/__init__.py +38 -0
- attune/test_generator/__main__.py +14 -0
- attune/test_generator/cli.py +234 -0
- attune/test_generator/generator.py +355 -0
- attune/test_generator/risk_analyzer.py +216 -0
- attune/test_generator/templates/unit_test.py.jinja2 +272 -0
- attune/tier_recommender.py +384 -0
- attune/tools.py +183 -0
- attune/trust/__init__.py +28 -0
- attune/trust/circuit_breaker.py +579 -0
- attune/trust_building.py +527 -0
- attune/validation/__init__.py +19 -0
- attune/validation/xml_validator.py +281 -0
- attune/vscode_bridge.py +173 -0
- attune/workflow_commands.py +780 -0
- attune/workflow_patterns/__init__.py +33 -0
- attune/workflow_patterns/behavior.py +249 -0
- attune/workflow_patterns/core.py +76 -0
- attune/workflow_patterns/output.py +99 -0
- attune/workflow_patterns/registry.py +255 -0
- attune/workflow_patterns/structural.py +288 -0
- attune/workflows/__init__.py +539 -0
- attune/workflows/autonomous_test_gen.py +1268 -0
- attune/workflows/base.py +2667 -0
- attune/workflows/batch_processing.py +342 -0
- attune/workflows/bug_predict.py +1084 -0
- attune/workflows/builder.py +273 -0
- attune/workflows/caching.py +253 -0
- attune/workflows/code_review.py +1048 -0
- attune/workflows/code_review_adapters.py +312 -0
- attune/workflows/code_review_pipeline.py +722 -0
- attune/workflows/config.py +645 -0
- attune/workflows/dependency_check.py +644 -0
- attune/workflows/document_gen/__init__.py +25 -0
- attune/workflows/document_gen/config.py +30 -0
- attune/workflows/document_gen/report_formatter.py +162 -0
- attune/workflows/document_gen/workflow.py +1426 -0
- attune/workflows/document_manager.py +216 -0
- attune/workflows/document_manager_README.md +134 -0
- attune/workflows/documentation_orchestrator.py +1205 -0
- attune/workflows/history.py +510 -0
- attune/workflows/keyboard_shortcuts/__init__.py +39 -0
- attune/workflows/keyboard_shortcuts/generators.py +391 -0
- attune/workflows/keyboard_shortcuts/parsers.py +416 -0
- attune/workflows/keyboard_shortcuts/prompts.py +295 -0
- attune/workflows/keyboard_shortcuts/schema.py +193 -0
- attune/workflows/keyboard_shortcuts/workflow.py +509 -0
- attune/workflows/llm_base.py +363 -0
- attune/workflows/manage_docs.py +87 -0
- attune/workflows/manage_docs_README.md +134 -0
- attune/workflows/manage_documentation.py +821 -0
- attune/workflows/new_sample_workflow1.py +149 -0
- attune/workflows/new_sample_workflow1_README.md +150 -0
- attune/workflows/orchestrated_health_check.py +849 -0
- attune/workflows/orchestrated_release_prep.py +600 -0
- attune/workflows/output.py +413 -0
- attune/workflows/perf_audit.py +863 -0
- attune/workflows/pr_review.py +762 -0
- attune/workflows/progress.py +785 -0
- attune/workflows/progress_server.py +322 -0
- attune/workflows/progressive/README 2.md +454 -0
- attune/workflows/progressive/README.md +454 -0
- attune/workflows/progressive/__init__.py +82 -0
- attune/workflows/progressive/cli.py +219 -0
- attune/workflows/progressive/core.py +488 -0
- attune/workflows/progressive/orchestrator.py +723 -0
- attune/workflows/progressive/reports.py +520 -0
- attune/workflows/progressive/telemetry.py +274 -0
- attune/workflows/progressive/test_gen.py +495 -0
- attune/workflows/progressive/workflow.py +589 -0
- attune/workflows/refactor_plan.py +694 -0
- attune/workflows/release_prep.py +895 -0
- attune/workflows/release_prep_crew.py +969 -0
- attune/workflows/research_synthesis.py +404 -0
- attune/workflows/routing.py +168 -0
- attune/workflows/secure_release.py +593 -0
- attune/workflows/security_adapters.py +297 -0
- attune/workflows/security_audit.py +1329 -0
- attune/workflows/security_audit_phase3.py +355 -0
- attune/workflows/seo_optimization.py +633 -0
- attune/workflows/step_config.py +234 -0
- attune/workflows/telemetry_mixin.py +269 -0
- attune/workflows/test5.py +125 -0
- attune/workflows/test5_README.md +158 -0
- attune/workflows/test_coverage_boost_crew.py +849 -0
- attune/workflows/test_gen/__init__.py +52 -0
- attune/workflows/test_gen/ast_analyzer.py +249 -0
- attune/workflows/test_gen/config.py +88 -0
- attune/workflows/test_gen/data_models.py +38 -0
- attune/workflows/test_gen/report_formatter.py +289 -0
- attune/workflows/test_gen/test_templates.py +381 -0
- attune/workflows/test_gen/workflow.py +655 -0
- attune/workflows/test_gen.py +54 -0
- attune/workflows/test_gen_behavioral.py +477 -0
- attune/workflows/test_gen_parallel.py +341 -0
- attune/workflows/test_lifecycle.py +526 -0
- attune/workflows/test_maintenance.py +627 -0
- attune/workflows/test_maintenance_cli.py +590 -0
- attune/workflows/test_maintenance_crew.py +840 -0
- attune/workflows/test_runner.py +622 -0
- attune/workflows/tier_tracking.py +531 -0
- attune/workflows/xml_enhanced_crew.py +285 -0
- attune_ai-2.0.0.dist-info/METADATA +1026 -0
- attune_ai-2.0.0.dist-info/RECORD +457 -0
- attune_ai-2.0.0.dist-info/WHEEL +5 -0
- attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
- attune_ai-2.0.0.dist-info/top_level.txt +5 -0
- attune_healthcare/__init__.py +13 -0
- attune_healthcare/monitors/__init__.py +9 -0
- attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
- attune_healthcare/monitors/monitoring/__init__.py +44 -0
- attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
- attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
- attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
- attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
- attune_llm/README.md +553 -0
- attune_llm/__init__.py +28 -0
- attune_llm/agent_factory/__init__.py +53 -0
- attune_llm/agent_factory/adapters/__init__.py +85 -0
- attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
- attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
- attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
- attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
- attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
- attune_llm/agent_factory/adapters/native.py +228 -0
- attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
- attune_llm/agent_factory/base.py +305 -0
- attune_llm/agent_factory/crews/__init__.py +67 -0
- attune_llm/agent_factory/crews/code_review.py +1113 -0
- attune_llm/agent_factory/crews/health_check.py +1262 -0
- attune_llm/agent_factory/crews/refactoring.py +1128 -0
- attune_llm/agent_factory/crews/security_audit.py +1018 -0
- attune_llm/agent_factory/decorators.py +287 -0
- attune_llm/agent_factory/factory.py +558 -0
- attune_llm/agent_factory/framework.py +193 -0
- attune_llm/agent_factory/memory_integration.py +328 -0
- attune_llm/agent_factory/resilient.py +320 -0
- attune_llm/agents_md/__init__.py +22 -0
- attune_llm/agents_md/loader.py +218 -0
- attune_llm/agents_md/parser.py +271 -0
- attune_llm/agents_md/registry.py +307 -0
- attune_llm/claude_memory.py +466 -0
- attune_llm/cli/__init__.py +8 -0
- attune_llm/cli/sync_claude.py +487 -0
- attune_llm/code_health.py +1313 -0
- attune_llm/commands/__init__.py +51 -0
- attune_llm/commands/context.py +375 -0
- attune_llm/commands/loader.py +301 -0
- attune_llm/commands/models.py +231 -0
- attune_llm/commands/parser.py +371 -0
- attune_llm/commands/registry.py +429 -0
- attune_llm/config/__init__.py +29 -0
- attune_llm/config/unified.py +291 -0
- attune_llm/context/__init__.py +22 -0
- attune_llm/context/compaction.py +455 -0
- attune_llm/context/manager.py +434 -0
- attune_llm/contextual_patterns.py +361 -0
- attune_llm/core.py +907 -0
- attune_llm/git_pattern_extractor.py +435 -0
- attune_llm/hooks/__init__.py +24 -0
- attune_llm/hooks/config.py +306 -0
- attune_llm/hooks/executor.py +289 -0
- attune_llm/hooks/registry.py +302 -0
- attune_llm/hooks/scripts/__init__.py +39 -0
- attune_llm/hooks/scripts/evaluate_session.py +201 -0
- attune_llm/hooks/scripts/first_time_init.py +285 -0
- attune_llm/hooks/scripts/pre_compact.py +207 -0
- attune_llm/hooks/scripts/session_end.py +183 -0
- attune_llm/hooks/scripts/session_start.py +163 -0
- attune_llm/hooks/scripts/suggest_compact.py +225 -0
- attune_llm/learning/__init__.py +30 -0
- attune_llm/learning/evaluator.py +438 -0
- attune_llm/learning/extractor.py +514 -0
- attune_llm/learning/storage.py +560 -0
- attune_llm/levels.py +227 -0
- attune_llm/pattern_confidence.py +414 -0
- attune_llm/pattern_resolver.py +272 -0
- attune_llm/pattern_summary.py +350 -0
- attune_llm/providers.py +967 -0
- attune_llm/routing/__init__.py +32 -0
- attune_llm/routing/model_router.py +362 -0
- attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
- attune_llm/security/PHASE2_COMPLETE.md +384 -0
- attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- attune_llm/security/QUICK_REFERENCE.md +316 -0
- attune_llm/security/README.md +262 -0
- attune_llm/security/__init__.py +62 -0
- attune_llm/security/audit_logger.py +929 -0
- attune_llm/security/audit_logger_example.py +152 -0
- attune_llm/security/pii_scrubber.py +640 -0
- attune_llm/security/secrets_detector.py +678 -0
- attune_llm/security/secrets_detector_example.py +304 -0
- attune_llm/security/secure_memdocs.py +1192 -0
- attune_llm/security/secure_memdocs_example.py +278 -0
- attune_llm/session_status.py +745 -0
- attune_llm/state.py +246 -0
- attune_llm/utils/__init__.py +5 -0
- attune_llm/utils/tokens.py +349 -0
- attune_software/SOFTWARE_PLUGIN_README.md +57 -0
- attune_software/__init__.py +13 -0
- attune_software/cli/__init__.py +120 -0
- attune_software/cli/inspect.py +362 -0
- attune_software/cli.py +574 -0
- attune_software/plugin.py +188 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- workflow_scaffolding/generator.py +265 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Test Generation Workflow Package.
|
|
2
|
+
|
|
3
|
+
Generates tests targeting areas with historical bugs and low coverage.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Core workflow
|
|
10
|
+
# AST analyzer
|
|
11
|
+
from .ast_analyzer import ASTFunctionAnalyzer
|
|
12
|
+
|
|
13
|
+
# Configuration
|
|
14
|
+
from .config import DEFAULT_SKIP_PATTERNS, TEST_GEN_STEPS
|
|
15
|
+
|
|
16
|
+
# Data models
|
|
17
|
+
from .data_models import ClassSignature, FunctionSignature
|
|
18
|
+
|
|
19
|
+
# Report formatter
|
|
20
|
+
from .report_formatter import format_test_gen_report
|
|
21
|
+
|
|
22
|
+
# Test generation templates
|
|
23
|
+
from .test_templates import (
|
|
24
|
+
generate_test_cases_for_params,
|
|
25
|
+
generate_test_for_class,
|
|
26
|
+
generate_test_for_function,
|
|
27
|
+
get_param_test_values,
|
|
28
|
+
get_type_assertion,
|
|
29
|
+
)
|
|
30
|
+
from .workflow import TestGenerationWorkflow, main
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
# Workflow
|
|
34
|
+
"TestGenerationWorkflow",
|
|
35
|
+
"main",
|
|
36
|
+
# Data models
|
|
37
|
+
"FunctionSignature",
|
|
38
|
+
"ClassSignature",
|
|
39
|
+
# AST analyzer
|
|
40
|
+
"ASTFunctionAnalyzer",
|
|
41
|
+
# Configuration
|
|
42
|
+
"DEFAULT_SKIP_PATTERNS",
|
|
43
|
+
"TEST_GEN_STEPS",
|
|
44
|
+
# Test templates
|
|
45
|
+
"generate_test_for_function",
|
|
46
|
+
"generate_test_for_class",
|
|
47
|
+
"generate_test_cases_for_params",
|
|
48
|
+
"get_type_assertion",
|
|
49
|
+
"get_param_test_values",
|
|
50
|
+
# Report formatter
|
|
51
|
+
"format_test_gen_report",
|
|
52
|
+
]
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"""AST-based Function and Class Analyzer.
|
|
2
|
+
|
|
3
|
+
Extracts function signatures, exception types, side effects, and complexity
|
|
4
|
+
from Python source code using AST parsing.
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart-AI-Memory
|
|
7
|
+
Licensed under Fair Source License 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import ast
|
|
11
|
+
|
|
12
|
+
from .data_models import ClassSignature, FunctionSignature
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ASTFunctionAnalyzer(ast.NodeVisitor):
|
|
16
|
+
"""AST-based function analyzer for accurate test generation.
|
|
17
|
+
|
|
18
|
+
Extracts:
|
|
19
|
+
- Function signatures with types
|
|
20
|
+
- Exception types raised
|
|
21
|
+
- Side effects detection
|
|
22
|
+
- Complexity estimation
|
|
23
|
+
|
|
24
|
+
Parse errors are tracked in the `last_error` attribute for debugging.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self):
|
|
28
|
+
self.functions: list[FunctionSignature] = []
|
|
29
|
+
self.classes: list[ClassSignature] = []
|
|
30
|
+
self._current_class: str | None = None
|
|
31
|
+
self.last_error: str | None = None # Track parse errors for debugging
|
|
32
|
+
|
|
33
|
+
def analyze(
|
|
34
|
+
self,
|
|
35
|
+
code: str,
|
|
36
|
+
file_path: str = "",
|
|
37
|
+
) -> tuple[list[FunctionSignature], list[ClassSignature]]:
|
|
38
|
+
"""Analyze code and extract function/class signatures.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
code: Python source code to analyze
|
|
42
|
+
file_path: Optional file path for error reporting
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Tuple of (functions, classes) lists. If parsing fails,
|
|
46
|
+
returns empty lists and sets self.last_error with details.
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
self.last_error = None
|
|
50
|
+
try:
|
|
51
|
+
tree = ast.parse(code)
|
|
52
|
+
self.functions = []
|
|
53
|
+
self.classes = []
|
|
54
|
+
self.visit(tree)
|
|
55
|
+
return self.functions, self.classes
|
|
56
|
+
except SyntaxError as e:
|
|
57
|
+
# Track the error for debugging instead of silent failure
|
|
58
|
+
location = f" at line {e.lineno}" if e.lineno else ""
|
|
59
|
+
file_info = f" in {file_path}" if file_path else ""
|
|
60
|
+
self.last_error = f"SyntaxError{file_info}{location}: {e.msg}"
|
|
61
|
+
return [], []
|
|
62
|
+
|
|
63
|
+
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
|
|
64
|
+
"""Extract function signature."""
|
|
65
|
+
if self._current_class is None: # Only top-level functions
|
|
66
|
+
sig = self._extract_function_signature(node)
|
|
67
|
+
self.functions.append(sig)
|
|
68
|
+
# Don't visit nested functions - we only want top-level
|
|
69
|
+
else:
|
|
70
|
+
# Inside a class - this is a method, visit it
|
|
71
|
+
self.generic_visit(node)
|
|
72
|
+
|
|
73
|
+
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
|
|
74
|
+
"""Extract async function signature."""
|
|
75
|
+
if self._current_class is None:
|
|
76
|
+
sig = self._extract_function_signature(node, is_async=True)
|
|
77
|
+
self.functions.append(sig)
|
|
78
|
+
# Don't visit nested functions - we only want top-level
|
|
79
|
+
else:
|
|
80
|
+
# Inside a class - this is a method, visit it
|
|
81
|
+
self.generic_visit(node)
|
|
82
|
+
|
|
83
|
+
def visit_ClassDef(self, node: ast.ClassDef) -> None:
|
|
84
|
+
"""Extract class signature with methods."""
|
|
85
|
+
self._current_class = node.name
|
|
86
|
+
methods = []
|
|
87
|
+
init_params: list[tuple[str, str, str | None]] = []
|
|
88
|
+
|
|
89
|
+
# Extract base classes
|
|
90
|
+
base_classes = []
|
|
91
|
+
for base in node.bases:
|
|
92
|
+
if isinstance(base, ast.Name):
|
|
93
|
+
base_classes.append(base.id)
|
|
94
|
+
elif isinstance(base, ast.Attribute):
|
|
95
|
+
base_classes.append(ast.unparse(base))
|
|
96
|
+
|
|
97
|
+
# Detect if this is an Enum
|
|
98
|
+
enum_bases = {"Enum", "IntEnum", "StrEnum", "Flag", "IntFlag", "auto"}
|
|
99
|
+
is_enum = any(b in enum_bases for b in base_classes)
|
|
100
|
+
|
|
101
|
+
# Detect if this is a dataclass
|
|
102
|
+
is_dataclass = False
|
|
103
|
+
for decorator in node.decorator_list:
|
|
104
|
+
if isinstance(decorator, ast.Name) and decorator.id == "dataclass":
|
|
105
|
+
is_dataclass = True
|
|
106
|
+
elif isinstance(decorator, ast.Call):
|
|
107
|
+
if isinstance(decorator.func, ast.Name) and decorator.func.id == "dataclass":
|
|
108
|
+
is_dataclass = True
|
|
109
|
+
|
|
110
|
+
# Process methods
|
|
111
|
+
for item in node.body:
|
|
112
|
+
if isinstance(item, ast.FunctionDef | ast.AsyncFunctionDef):
|
|
113
|
+
method_sig = self._extract_function_signature(
|
|
114
|
+
item,
|
|
115
|
+
is_async=isinstance(item, ast.AsyncFunctionDef),
|
|
116
|
+
)
|
|
117
|
+
methods.append(method_sig)
|
|
118
|
+
|
|
119
|
+
# Extract __init__ params
|
|
120
|
+
if item.name == "__init__":
|
|
121
|
+
init_params = method_sig.params[1:] # Skip 'self'
|
|
122
|
+
|
|
123
|
+
# Count required init params (those without defaults)
|
|
124
|
+
required_init_params = sum(1 for p in init_params if p[2] is None)
|
|
125
|
+
|
|
126
|
+
self.classes.append(
|
|
127
|
+
ClassSignature(
|
|
128
|
+
name=node.name,
|
|
129
|
+
methods=methods,
|
|
130
|
+
init_params=init_params,
|
|
131
|
+
base_classes=base_classes,
|
|
132
|
+
docstring=ast.get_docstring(node),
|
|
133
|
+
is_enum=is_enum,
|
|
134
|
+
is_dataclass=is_dataclass,
|
|
135
|
+
required_init_params=required_init_params,
|
|
136
|
+
),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
self._current_class = None
|
|
140
|
+
# Don't call generic_visit to avoid processing methods again
|
|
141
|
+
|
|
142
|
+
def _extract_function_signature(
|
|
143
|
+
self,
|
|
144
|
+
node: ast.FunctionDef | ast.AsyncFunctionDef,
|
|
145
|
+
is_async: bool = False,
|
|
146
|
+
) -> FunctionSignature:
|
|
147
|
+
"""Extract detailed signature from function node."""
|
|
148
|
+
# Extract parameters with types and defaults
|
|
149
|
+
params = []
|
|
150
|
+
defaults = list(node.args.defaults)
|
|
151
|
+
num_defaults = len(defaults)
|
|
152
|
+
num_args = len(node.args.args)
|
|
153
|
+
|
|
154
|
+
for i, arg in enumerate(node.args.args):
|
|
155
|
+
param_name = arg.arg
|
|
156
|
+
param_type = ast.unparse(arg.annotation) if arg.annotation else "Any"
|
|
157
|
+
|
|
158
|
+
# Calculate default index
|
|
159
|
+
default_idx = i - (num_args - num_defaults)
|
|
160
|
+
default_val = None
|
|
161
|
+
if default_idx >= 0:
|
|
162
|
+
try:
|
|
163
|
+
default_val = ast.unparse(defaults[default_idx])
|
|
164
|
+
except Exception:
|
|
165
|
+
default_val = "..."
|
|
166
|
+
|
|
167
|
+
params.append((param_name, param_type, default_val))
|
|
168
|
+
|
|
169
|
+
# Extract return type
|
|
170
|
+
return_type = ast.unparse(node.returns) if node.returns else None
|
|
171
|
+
|
|
172
|
+
# Find raised exceptions
|
|
173
|
+
raises: set[str] = set()
|
|
174
|
+
for child in ast.walk(node):
|
|
175
|
+
if isinstance(child, ast.Raise) and child.exc:
|
|
176
|
+
if isinstance(child.exc, ast.Call):
|
|
177
|
+
if isinstance(child.exc.func, ast.Name):
|
|
178
|
+
raises.add(child.exc.func.id)
|
|
179
|
+
elif isinstance(child.exc.func, ast.Attribute):
|
|
180
|
+
raises.add(child.exc.func.attr)
|
|
181
|
+
elif isinstance(child.exc, ast.Name):
|
|
182
|
+
raises.add(child.exc.id)
|
|
183
|
+
|
|
184
|
+
# Detect side effects (simple heuristic)
|
|
185
|
+
has_side_effects = self._detect_side_effects(node)
|
|
186
|
+
|
|
187
|
+
# Estimate complexity
|
|
188
|
+
complexity = self._estimate_complexity(node)
|
|
189
|
+
|
|
190
|
+
# Extract decorators
|
|
191
|
+
decorators = []
|
|
192
|
+
for dec in node.decorator_list:
|
|
193
|
+
if isinstance(dec, ast.Name):
|
|
194
|
+
decorators.append(dec.id)
|
|
195
|
+
elif isinstance(dec, ast.Attribute):
|
|
196
|
+
decorators.append(ast.unparse(dec))
|
|
197
|
+
elif isinstance(dec, ast.Call):
|
|
198
|
+
if isinstance(dec.func, ast.Name):
|
|
199
|
+
decorators.append(dec.func.id)
|
|
200
|
+
|
|
201
|
+
return FunctionSignature(
|
|
202
|
+
name=node.name,
|
|
203
|
+
params=params,
|
|
204
|
+
return_type=return_type,
|
|
205
|
+
is_async=is_async or isinstance(node, ast.AsyncFunctionDef),
|
|
206
|
+
raises=raises,
|
|
207
|
+
has_side_effects=has_side_effects,
|
|
208
|
+
docstring=ast.get_docstring(node),
|
|
209
|
+
complexity=complexity,
|
|
210
|
+
decorators=decorators,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
def _detect_side_effects(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> bool:
|
|
214
|
+
"""Detect if function has side effects (writes to files, global state, etc.)."""
|
|
215
|
+
side_effect_names = {
|
|
216
|
+
"print",
|
|
217
|
+
"write",
|
|
218
|
+
"open",
|
|
219
|
+
"save",
|
|
220
|
+
"delete",
|
|
221
|
+
"remove",
|
|
222
|
+
"update",
|
|
223
|
+
"insert",
|
|
224
|
+
"execute",
|
|
225
|
+
"send",
|
|
226
|
+
"post",
|
|
227
|
+
"put",
|
|
228
|
+
"patch",
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
for child in ast.walk(node):
|
|
232
|
+
if isinstance(child, ast.Call):
|
|
233
|
+
if isinstance(child.func, ast.Name):
|
|
234
|
+
if child.func.id.lower() in side_effect_names:
|
|
235
|
+
return True
|
|
236
|
+
elif isinstance(child.func, ast.Attribute):
|
|
237
|
+
if child.func.attr.lower() in side_effect_names:
|
|
238
|
+
return True
|
|
239
|
+
return False
|
|
240
|
+
|
|
241
|
+
def _estimate_complexity(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> int:
|
|
242
|
+
"""Estimate cyclomatic complexity (simplified)."""
|
|
243
|
+
complexity = 1
|
|
244
|
+
for child in ast.walk(node):
|
|
245
|
+
if isinstance(child, ast.If | ast.While | ast.For | ast.ExceptHandler):
|
|
246
|
+
complexity += 1
|
|
247
|
+
elif isinstance(child, ast.BoolOp):
|
|
248
|
+
complexity += len(child.values) - 1
|
|
249
|
+
return complexity
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Test Generation Configuration.
|
|
2
|
+
|
|
3
|
+
Default patterns and step configurations for test generation workflow.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from ..step_config import WorkflowStepConfig
|
|
10
|
+
|
|
11
|
+
# =============================================================================
|
|
12
|
+
# Default Configuration
|
|
13
|
+
# =============================================================================
|
|
14
|
+
|
|
15
|
+
# Directories to skip during file scanning (configurable via input_data["skip_patterns"])
|
|
16
|
+
DEFAULT_SKIP_PATTERNS = [
|
|
17
|
+
# Version control
|
|
18
|
+
".git",
|
|
19
|
+
".hg",
|
|
20
|
+
".svn",
|
|
21
|
+
# Dependencies
|
|
22
|
+
"node_modules",
|
|
23
|
+
"bower_components",
|
|
24
|
+
"vendor",
|
|
25
|
+
# Python caches
|
|
26
|
+
"__pycache__",
|
|
27
|
+
".mypy_cache",
|
|
28
|
+
".pytest_cache",
|
|
29
|
+
".ruff_cache",
|
|
30
|
+
".hypothesis",
|
|
31
|
+
# Virtual environments
|
|
32
|
+
"venv",
|
|
33
|
+
".venv",
|
|
34
|
+
"env",
|
|
35
|
+
".env",
|
|
36
|
+
"virtualenv",
|
|
37
|
+
".virtualenv",
|
|
38
|
+
# Build tools
|
|
39
|
+
".tox",
|
|
40
|
+
".nox",
|
|
41
|
+
# Build outputs
|
|
42
|
+
"build",
|
|
43
|
+
"dist",
|
|
44
|
+
"eggs",
|
|
45
|
+
".eggs",
|
|
46
|
+
"site-packages",
|
|
47
|
+
# IDE
|
|
48
|
+
".idea",
|
|
49
|
+
".vscode",
|
|
50
|
+
# Framework-specific
|
|
51
|
+
"migrations",
|
|
52
|
+
"alembic",
|
|
53
|
+
# Documentation
|
|
54
|
+
"_build",
|
|
55
|
+
"docs/_build",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
# Define step configurations for executor-based execution
|
|
59
|
+
TEST_GEN_STEPS = {
|
|
60
|
+
"identify": WorkflowStepConfig(
|
|
61
|
+
name="identify",
|
|
62
|
+
task_type="triage", # Cheap tier task
|
|
63
|
+
tier_hint="cheap",
|
|
64
|
+
description="Identify files needing tests",
|
|
65
|
+
max_tokens=2000,
|
|
66
|
+
),
|
|
67
|
+
"analyze": WorkflowStepConfig(
|
|
68
|
+
name="analyze",
|
|
69
|
+
task_type="code_analysis", # Capable tier task
|
|
70
|
+
tier_hint="capable",
|
|
71
|
+
description="Analyze code structure for test generation",
|
|
72
|
+
max_tokens=3000,
|
|
73
|
+
),
|
|
74
|
+
"generate": WorkflowStepConfig(
|
|
75
|
+
name="generate",
|
|
76
|
+
task_type="code_generation", # Capable tier task
|
|
77
|
+
tier_hint="capable",
|
|
78
|
+
description="Generate test cases",
|
|
79
|
+
max_tokens=4000,
|
|
80
|
+
),
|
|
81
|
+
"review": WorkflowStepConfig(
|
|
82
|
+
name="review",
|
|
83
|
+
task_type="final_review", # Premium tier task
|
|
84
|
+
tier_hint="premium",
|
|
85
|
+
description="Review and improve generated test suite",
|
|
86
|
+
max_tokens=3000,
|
|
87
|
+
),
|
|
88
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Test Generation Data Models.
|
|
2
|
+
|
|
3
|
+
Dataclass definitions for function and class signatures.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class FunctionSignature:
|
|
14
|
+
"""Detailed function analysis for test generation."""
|
|
15
|
+
|
|
16
|
+
name: str
|
|
17
|
+
params: list[tuple[str, str, str | None]] # (name, type_hint, default)
|
|
18
|
+
return_type: str | None
|
|
19
|
+
is_async: bool
|
|
20
|
+
raises: set[str]
|
|
21
|
+
has_side_effects: bool
|
|
22
|
+
docstring: str | None
|
|
23
|
+
complexity: int = 1 # Rough complexity estimate
|
|
24
|
+
decorators: list[str] = field(default_factory=list)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class ClassSignature:
|
|
29
|
+
"""Detailed class analysis for test generation."""
|
|
30
|
+
|
|
31
|
+
name: str
|
|
32
|
+
methods: list[FunctionSignature]
|
|
33
|
+
init_params: list[tuple[str, str, str | None]] # Constructor params
|
|
34
|
+
base_classes: list[str]
|
|
35
|
+
docstring: str | None
|
|
36
|
+
is_enum: bool = False # True if class inherits from Enum
|
|
37
|
+
is_dataclass: bool = False # True if class has @dataclass decorator
|
|
38
|
+
required_init_params: int = 0 # Number of params without defaults
|