code2llm 0.5.174__tar.gz → 0.5.175__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.
- {code2llm-0.5.174/code2llm.egg-info → code2llm-0.5.175}/PKG-INFO +6 -6
- {code2llm-0.5.174 → code2llm-0.5.175}/README.md +5 -5
- code2llm-0.5.175/VERSION +1 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/__init__.py +1 -1
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_exports/orchestrator.py +4 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/base.py +26 -2
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/flow_constants.py +28 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/map/header.py +4 -1
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/map_exporter.py +1 -4
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/planfile_tickets.py +6 -1
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/metrics_duplicates.py +4 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/mermaid/png.py +36 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/nlp/__init__.py +1 -1
- {code2llm-0.5.174 → code2llm-0.5.175/code2llm.egg-info}/PKG-INFO +6 -6
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm.egg-info/SOURCES.txt +2 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/pyproject.toml +1 -1
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_dup_groups.py +61 -1
- code2llm-0.5.175/tests/test_export_profile_contract.py +28 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_format_quality.py +3 -0
- code2llm-0.5.175/tests/test_mermaid_png.py +29 -0
- code2llm-0.5.174/VERSION +0 -1
- {code2llm-0.5.174 → code2llm-0.5.175}/LICENSE +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/MANIFEST.in +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/__main__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/_data_impl.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/call_graph.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/cfg.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/coupling.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/data_analysis.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/dfg.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/pipeline_classifier.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/pipeline_detector.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/pipeline_resolver.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/side_effects.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/smells.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/type_inference.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/utils/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/analysis/utils/ast_helpers.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/api.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_analysis.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_commands.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_exports/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_exports/code2logic.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_exports/formats.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_exports/orchestrator_chunked.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_exports/orchestrator_constants.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_exports/orchestrator_handlers.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_exports/prompt.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/cli_parser.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/analyzer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/ast_registry.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/config.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/export_pipeline.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/file_analyzer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/file_cache.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/file_filter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/gitignore.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/incremental.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/_c_parser.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/_calls.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/_complexity.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/base.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/cpp.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/csharp.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/generic.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/go_lang.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/java.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/php.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/ruby.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/rust.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/ts_extractors.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/ts_parser.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/lang/typescript.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/large_repo.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/models.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/persistent_cache.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/refactoring.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/repo_files.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/source_classifier.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/streaming/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/streaming/cache.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/streaming/incremental.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/streaming/prioritizer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/streaming/scanner.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/streaming/strategies.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/streaming_analyzer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/core/toon_size_manager.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/article_view.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/context_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/context_view.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/dashboard_data.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/dashboard_renderer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/evolution/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/evolution/computation.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/evolution/constants.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/evolution/exclusion.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/evolution/render.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/evolution/yaml_export.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/evolution_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/flow_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/flow_renderer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/html_dashboard.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/index_generator/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/index_generator/renderer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/index_generator/scanner.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/index_generator.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/json_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/llm_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/map/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/map/alerts.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/map/details.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/map/module_list.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/map/utils.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/map/yaml_export.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid/calls.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid/classic.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid/compact.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid/flow_compact.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid/flow_detailed.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid/flow_full.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid/utils.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/project_yaml/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/project_yaml/constants.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/project_yaml/core.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/project_yaml/evolution.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/project_yaml/health.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/project_yaml/hotspots.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/project_yaml/modules.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/project_yaml_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/readme/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/readme/content.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/readme/files.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/readme/insights.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/readme/sections.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/readme_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/report_generators.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/_render_coupling_helpers.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/_render_section_helpers.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/constants.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/helpers.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/metrics.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/metrics_core.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/metrics_health.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/module_detail.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon/renderer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/toon_view.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/validate_project.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/exporters/yaml_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/_utils.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_flow/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_flow/analysis.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_flow/cli.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_flow/generator.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_flow/nodes.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_flow/parsing.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_flow/utils.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_flow.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/llm_task.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/mermaid/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/mermaid/fix.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/mermaid/validation.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/generators/mermaid.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/nlp/config.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/nlp/entity_resolution.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/nlp/intent_matching.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/nlp/normalization.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/nlp/pipeline.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/parsers/toon_parser.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/patterns/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/patterns/detector.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/refactor/__init__.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm/refactor/prompt_engine.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm.egg-info/dependency_links.txt +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm.egg-info/entry_points.txt +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm.egg-info/requires.txt +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/code2llm.egg-info/top_level.txt +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/setup.cfg +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/setup.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_advanced_analysis.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_analyzer.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_cache_invalidation_e2e.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_calls_toon_export.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_declarative_collection.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_deep_analysis.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_edge_cases.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_export_cache_flags.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_file_analyzer_tagging.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_flow_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_multilanguage_e2e.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_nlp_pipeline.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_nonpython_cc_calls.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_orchestrator_cache_mtime.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_persistent_cache.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_pipeline_detector.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_planfile_tickets_exporter.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_project_toon_export.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_prompt_engine.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_prompt_txt.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_refactoring_engine.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_smells_data_clumps.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_smells_shotgun_surgery.py +0 -0
- {code2llm-0.5.174 → code2llm-0.5.175}/tests/test_toon_v2.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.175
|
|
4
4
|
Summary: High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries
|
|
5
5
|
Home-page: https://github.com/wronai/stts
|
|
6
6
|
Author: Tom Sapletta
|
|
@@ -67,13 +67,13 @@ Dynamic: requires-python
|
|
|
67
67
|
|
|
68
68
|
## AI Cost Tracking
|
|
69
69
|
|
|
70
|
-
     
|
|
71
|
+
  
|
|
72
72
|
|
|
73
|
-
- 🤖 **LLM usage:** $3.
|
|
74
|
-
- 👤 **Human dev:** ~$
|
|
73
|
+
- 🤖 **LLM usage:** $3.8035 (262 commits)
|
|
74
|
+
- 👤 **Human dev:** ~$10435 (104.3h @ $100/h, 30min dedup)
|
|
75
75
|
|
|
76
|
-
Generated on 2026-
|
|
76
|
+
Generated on 2026-08-01 using [openrouter/deep/deep-v4-pro](https://openrouter.ai/deep/deep-v4-pro)
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## AI Cost Tracking
|
|
4
4
|
|
|
5
|
-
     
|
|
6
|
+
  
|
|
7
7
|
|
|
8
|
-
- 🤖 **LLM usage:** $3.
|
|
9
|
-
- 👤 **Human dev:** ~$
|
|
8
|
+
- 🤖 **LLM usage:** $3.8035 (262 commits)
|
|
9
|
+
- 👤 **Human dev:** ~$10435 (104.3h @ $100/h, 30min dedup)
|
|
10
10
|
|
|
11
|
-
Generated on 2026-
|
|
11
|
+
Generated on 2026-08-01 using [openrouter/deep/deep-v4-pro](https://openrouter.ai/deep/deep-v4-pro)
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
code2llm-0.5.175/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.5.175
|
|
@@ -8,7 +8,7 @@ Includes NLP Processing Pipeline for query normalization, intent matching,
|
|
|
8
8
|
and entity resolution with multilingual support.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
__version__ = "0.5.
|
|
11
|
+
__version__ = "0.5.175"
|
|
12
12
|
__author__ = "STTS Project"
|
|
13
13
|
|
|
14
14
|
# Core analysis components (lightweight, always needed)
|
|
@@ -42,6 +42,10 @@ def _build_export_config(args, formats: List[str]) -> Dict[str, Any]:
|
|
|
42
42
|
"""Build config dict for export caching."""
|
|
43
43
|
return {
|
|
44
44
|
"formats": sorted(formats),
|
|
45
|
+
"mode": getattr(args, "mode", None),
|
|
46
|
+
"strategy": getattr(args, "strategy", None),
|
|
47
|
+
"exclude": sorted(str(item) for item in (getattr(args, "exclude", None) or [])),
|
|
48
|
+
"gitignore": getattr(args, "gitignore", None),
|
|
45
49
|
"png": getattr(args, "png", False),
|
|
46
50
|
"no_png": getattr(args, "no_png", False),
|
|
47
51
|
"flow_include_examples": getattr(args, "flow_include_examples", False),
|
|
@@ -7,6 +7,8 @@ Provides:
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from abc import ABC, abstractmethod
|
|
10
|
+
import os
|
|
11
|
+
import tempfile
|
|
10
12
|
from pathlib import Path
|
|
11
13
|
from typing import Any, Dict, Optional, Type, ClassVar
|
|
12
14
|
from code2llm.core.models import AnalysisResult
|
|
@@ -80,9 +82,31 @@ class BaseExporter(ABC):
|
|
|
80
82
|
return path
|
|
81
83
|
|
|
82
84
|
def _write_text(self, output_path: str, content: str) -> Path:
|
|
83
|
-
"""
|
|
85
|
+
"""Atomically write text content, ensuring the directory exists.
|
|
86
|
+
|
|
87
|
+
Analysis artifacts are consumed by background tools immediately after
|
|
88
|
+
generation. A same-directory temporary file plus ``os.replace`` keeps
|
|
89
|
+
readers from observing a truncated map while an export is in progress.
|
|
90
|
+
"""
|
|
84
91
|
path = self._ensure_dir(output_path)
|
|
85
|
-
|
|
92
|
+
temporary = None
|
|
93
|
+
try:
|
|
94
|
+
with tempfile.NamedTemporaryFile(
|
|
95
|
+
mode="w",
|
|
96
|
+
encoding="utf-8",
|
|
97
|
+
dir=path.parent,
|
|
98
|
+
prefix=f".{path.name}.",
|
|
99
|
+
suffix=".tmp",
|
|
100
|
+
delete=False,
|
|
101
|
+
) as handle:
|
|
102
|
+
handle.write(content)
|
|
103
|
+
handle.flush()
|
|
104
|
+
os.fsync(handle.fileno())
|
|
105
|
+
temporary = Path(handle.name)
|
|
106
|
+
os.replace(temporary, path)
|
|
107
|
+
finally:
|
|
108
|
+
if temporary is not None:
|
|
109
|
+
temporary.unlink(missing_ok=True)
|
|
86
110
|
return path
|
|
87
111
|
|
|
88
112
|
|
|
@@ -46,6 +46,15 @@ INTENTIONAL_DUP_COPY_MARKERS: tuple[str, ...] = (
|
|
|
46
46
|
"pc2/",
|
|
47
47
|
"examples/",
|
|
48
48
|
"-contract-",
|
|
49
|
+
"work/repos/",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# These repositories are deliberately separate execution planes. Classes with
|
|
53
|
+
# similar infrastructure-shaped APIs across two different agents are not
|
|
54
|
+
# consolidation candidates: sharing their implementations would couple the
|
|
55
|
+
# independent diagnostic, repair, and validation boundaries.
|
|
56
|
+
INDEPENDENT_AGENT_REPOSITORIES = frozenset(
|
|
57
|
+
{"doctor-agent", "repair-agent", "validator-agent"}
|
|
49
58
|
)
|
|
50
59
|
|
|
51
60
|
|
|
@@ -58,6 +67,25 @@ def is_intentional_duplicate_copy(path: str) -> bool:
|
|
|
58
67
|
return any(marker in norm for marker in INTENTIONAL_DUP_COPY_MARKERS)
|
|
59
68
|
|
|
60
69
|
|
|
70
|
+
@lru_cache(maxsize=4096)
|
|
71
|
+
def _independent_agent_repository(path: str) -> str | None:
|
|
72
|
+
"""Return the independent agent repository segment present in *path*."""
|
|
73
|
+
if not path:
|
|
74
|
+
return None
|
|
75
|
+
parts = path.replace("\\", "/").lower().split("/")
|
|
76
|
+
return next((part for part in parts if part in INDEPENDENT_AGENT_REPOSITORIES), None)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@lru_cache(maxsize=4096)
|
|
80
|
+
def is_intentional_duplicate_pair(path_a: str, path_b: str) -> bool:
|
|
81
|
+
"""True when two similar classes belong to intentionally parallel copies."""
|
|
82
|
+
if is_intentional_duplicate_copy(path_a) or is_intentional_duplicate_copy(path_b):
|
|
83
|
+
return True
|
|
84
|
+
repo_a = _independent_agent_repository(path_a)
|
|
85
|
+
repo_b = _independent_agent_repository(path_b)
|
|
86
|
+
return repo_a is not None and repo_b is not None and repo_a != repo_b
|
|
87
|
+
|
|
88
|
+
|
|
61
89
|
@lru_cache(maxsize=4096)
|
|
62
90
|
def is_excluded_path(path: str) -> bool:
|
|
63
91
|
"""Return True if *path* matches any standard exclusion pattern (venv, cache, etc.)."""
|
|
@@ -8,6 +8,8 @@ from code2llm.core.models import AnalysisResult, FunctionInfo, ModuleInfo
|
|
|
8
8
|
from .utils import count_total_lines, detect_languages
|
|
9
9
|
from .alerts import build_alerts, build_hotspots, load_evolution_trend
|
|
10
10
|
|
|
11
|
+
MAP_PRODUCER_HEADER = "# producer: code2llm | artifact: map.toon.yaml | schema: 1"
|
|
12
|
+
|
|
11
13
|
|
|
12
14
|
def render_header(
|
|
13
15
|
result: AnalysisResult, output_path: str, is_excluded_path
|
|
@@ -38,6 +40,7 @@ def render_header(
|
|
|
38
40
|
|
|
39
41
|
lines = [
|
|
40
42
|
f"# {project_name} | {stats_line['files']}f {stats_line['lines']}L | {lang_str} | {datetime.now().strftime('%Y-%m-%d')}", # noqa: E501
|
|
43
|
+
MAP_PRODUCER_HEADER,
|
|
41
44
|
f"# stats: {stats_line['funcs']} func | {stats_line['classes']} cls | {stats_line['files']} mod | CC̄={stats_line['avg_cc']} | critical:{stats_line['critical']} | cycles:{stats_line['cycles']}", # noqa: E501
|
|
42
45
|
alerts_line,
|
|
43
46
|
hotspots_line,
|
|
@@ -78,4 +81,4 @@ def _render_hotspots_line(funcs: List[FunctionInfo]) -> str:
|
|
|
78
81
|
return f"# hotspots[{len(hotspots)}]: {'; '.join(hotspots) if hotspots else 'none'}"
|
|
79
82
|
|
|
80
83
|
|
|
81
|
-
__all__ = ["render_header"]
|
|
84
|
+
__all__ = ["MAP_PRODUCER_HEADER", "render_header"]
|
|
@@ -41,10 +41,7 @@ class MapExporter(BaseExporter):
|
|
|
41
41
|
lines.extend(render_module_list(result, is_excluded_path))
|
|
42
42
|
lines.extend(render_details(result, is_excluded_path))
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
with open(path, "w", encoding="utf-8") as f:
|
|
46
|
-
f.write("\n".join(lines) + "\n")
|
|
47
|
-
return path
|
|
44
|
+
return self._write_text(output_path, "\n".join(lines) + "\n")
|
|
48
45
|
|
|
49
46
|
def export_to_yaml(
|
|
50
47
|
self, result: AnalysisResult, output_path: str, **kwargs
|
|
@@ -293,7 +293,10 @@ def _duplicate_class_tickets(result: AnalysisResult) -> list[PlanfileTicketSugge
|
|
|
293
293
|
|
|
294
294
|
def _duplicate_class_pairs(result: AnalysisResult) -> list[tuple[str, str, str]]:
|
|
295
295
|
"""Return (class_name, file_a, file_b) for each similar class pair."""
|
|
296
|
-
from code2llm.exporters.flow_constants import
|
|
296
|
+
from code2llm.exporters.flow_constants import (
|
|
297
|
+
is_intentional_duplicate_copy,
|
|
298
|
+
is_intentional_duplicate_pair,
|
|
299
|
+
)
|
|
297
300
|
|
|
298
301
|
pairs: list[tuple[str, str, str]] = []
|
|
299
302
|
classes = [
|
|
@@ -308,6 +311,8 @@ def _duplicate_class_pairs(result: AnalysisResult) -> list[tuple[str, str, str]]
|
|
|
308
311
|
for right in classes[index + 1 :]:
|
|
309
312
|
if left.name != right.name:
|
|
310
313
|
continue
|
|
314
|
+
if is_intentional_duplicate_pair(left.file, right.file):
|
|
315
|
+
continue
|
|
311
316
|
right_methods = _method_names(right)
|
|
312
317
|
if len(right_methods) < 3:
|
|
313
318
|
continue
|
|
@@ -7,6 +7,8 @@ from typing import Any, Dict, List, Optional, Set
|
|
|
7
7
|
|
|
8
8
|
from code2llm.core.models import AnalysisResult, ClassInfo
|
|
9
9
|
|
|
10
|
+
from code2llm.exporters.flow_constants import is_intentional_duplicate_pair
|
|
11
|
+
|
|
10
12
|
from .helpers import _is_excluded, _rel_path, is_intentional_duplicate_copy
|
|
11
13
|
|
|
12
14
|
|
|
@@ -47,6 +49,8 @@ class DuplicatesMetricsComputer:
|
|
|
47
49
|
qb, cb = class_list[j]
|
|
48
50
|
if ca.name != cb.name:
|
|
49
51
|
continue
|
|
52
|
+
if is_intentional_duplicate_pair(ca.file, cb.file):
|
|
53
|
+
continue
|
|
50
54
|
|
|
51
55
|
methods_b = {m.split(".")[-1] for m in cb.methods}
|
|
52
56
|
if len(methods_b) < 3:
|
|
@@ -4,6 +4,7 @@ import os
|
|
|
4
4
|
import subprocess
|
|
5
5
|
import tempfile
|
|
6
6
|
import json
|
|
7
|
+
import shutil
|
|
7
8
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import List, Optional
|
|
@@ -17,6 +18,38 @@ from .validation import validate_mermaid_file
|
|
|
17
18
|
from .fix import fix_mermaid_file
|
|
18
19
|
|
|
19
20
|
|
|
21
|
+
_BROWSER_ENV_VARS = (
|
|
22
|
+
"PUPPETEER_EXECUTABLE_PATH",
|
|
23
|
+
"CHROME_PATH",
|
|
24
|
+
"GOOGLE_CHROME_BIN",
|
|
25
|
+
)
|
|
26
|
+
_BROWSER_COMMANDS = (
|
|
27
|
+
"google-chrome",
|
|
28
|
+
"google-chrome-stable",
|
|
29
|
+
"chromium",
|
|
30
|
+
"chromium-browser",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _find_browser_executable() -> Optional[str]:
|
|
35
|
+
"""Return an explicit Chrome/Chromium path suitable for Puppeteer.
|
|
36
|
+
|
|
37
|
+
Mermaid CLI bundles puppeteer-core, which does not download Chromium on
|
|
38
|
+
installation. Prefer an explicitly configured browser and otherwise use
|
|
39
|
+
the system browser already available on the PATH.
|
|
40
|
+
"""
|
|
41
|
+
for variable in _BROWSER_ENV_VARS:
|
|
42
|
+
candidate = os.getenv(variable)
|
|
43
|
+
if candidate and Path(candidate).is_file() and os.access(candidate, os.X_OK):
|
|
44
|
+
return candidate
|
|
45
|
+
|
|
46
|
+
for command in _BROWSER_COMMANDS:
|
|
47
|
+
candidate = shutil.which(command)
|
|
48
|
+
if candidate:
|
|
49
|
+
return candidate
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
|
|
20
53
|
def _is_png_fresh(mmd_file: Path, output_dir: Path) -> bool:
|
|
21
54
|
"""Check if PNG exists and is newer than MMD source."""
|
|
22
55
|
png_file = output_dir / f"{mmd_file.stem}.png"
|
|
@@ -115,6 +148,9 @@ def _setup_puppeteer_config() -> tuple[int, int, Optional[str], Optional[str]]:
|
|
|
115
148
|
puppeteer_cfg = {
|
|
116
149
|
"args": ["--no-sandbox", "--disable-setuid-sandbox"],
|
|
117
150
|
}
|
|
151
|
+
browser_executable = _find_browser_executable()
|
|
152
|
+
if browser_executable:
|
|
153
|
+
puppeteer_cfg["executablePath"] = browser_executable
|
|
118
154
|
with tempfile.NamedTemporaryFile(
|
|
119
155
|
mode="w", suffix=".json", delete=False
|
|
120
156
|
) as tmp_pcfg:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.175
|
|
4
4
|
Summary: High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries
|
|
5
5
|
Home-page: https://github.com/wronai/stts
|
|
6
6
|
Author: Tom Sapletta
|
|
@@ -67,13 +67,13 @@ Dynamic: requires-python
|
|
|
67
67
|
|
|
68
68
|
## AI Cost Tracking
|
|
69
69
|
|
|
70
|
-
     
|
|
71
|
+
  
|
|
72
72
|
|
|
73
|
-
- 🤖 **LLM usage:** $3.
|
|
74
|
-
- 👤 **Human dev:** ~$
|
|
73
|
+
- 🤖 **LLM usage:** $3.8035 (262 commits)
|
|
74
|
+
- 👤 **Human dev:** ~$10435 (104.3h @ $100/h, 30min dedup)
|
|
75
75
|
|
|
76
|
-
Generated on 2026-
|
|
76
|
+
Generated on 2026-08-01 using [openrouter/deep/deep-v4-pro](https://openrouter.ai/deep/deep-v4-pro)
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
@@ -189,9 +189,11 @@ tests/test_deep_analysis.py
|
|
|
189
189
|
tests/test_dup_groups.py
|
|
190
190
|
tests/test_edge_cases.py
|
|
191
191
|
tests/test_export_cache_flags.py
|
|
192
|
+
tests/test_export_profile_contract.py
|
|
192
193
|
tests/test_file_analyzer_tagging.py
|
|
193
194
|
tests/test_flow_exporter.py
|
|
194
195
|
tests/test_format_quality.py
|
|
196
|
+
tests/test_mermaid_png.py
|
|
195
197
|
tests/test_multilanguage_e2e.py
|
|
196
198
|
tests/test_nlp_pipeline.py
|
|
197
199
|
tests/test_nonpython_cc_calls.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code2llm"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.175"
|
|
8
8
|
description = "High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -5,7 +5,10 @@ from __future__ import annotations
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from code2llm.core.models import AnalysisResult, ClassInfo
|
|
8
|
-
from code2llm.exporters.flow_constants import
|
|
8
|
+
from code2llm.exporters.flow_constants import (
|
|
9
|
+
is_intentional_duplicate_copy,
|
|
10
|
+
is_intentional_duplicate_pair,
|
|
11
|
+
)
|
|
9
12
|
from code2llm.exporters.planfile_tickets import collect_planfile_tickets
|
|
10
13
|
from code2llm.exporters.toon.metrics_duplicates import DuplicatesMetricsComputer
|
|
11
14
|
from code2llm.exporters.toon.metrics_health import HealthMetricsComputer
|
|
@@ -26,9 +29,23 @@ def test_intentional_copy_paths_are_detected() -> None:
|
|
|
26
29
|
assert is_intentional_duplicate_copy("/repo/pc1/net-user-pl/handler.py")
|
|
27
30
|
assert is_intentional_duplicate_copy("/repo/examples/demo/foo.py")
|
|
28
31
|
assert is_intentional_duplicate_copy("/repo/urirun-contract-windowpair/x.py")
|
|
32
|
+
assert is_intentional_duplicate_copy(
|
|
33
|
+
"/repo/doctor-agent/work/repos/runtime/src/executor.py"
|
|
34
|
+
)
|
|
29
35
|
assert not is_intentional_duplicate_copy("/repo/app/src/handler.py")
|
|
30
36
|
|
|
31
37
|
|
|
38
|
+
def test_independent_agent_repositories_are_an_intentional_pair() -> None:
|
|
39
|
+
doctor = "/repo/doctor-agent/src/ifuri_doctor/command.py"
|
|
40
|
+
repair = "/repo/repair-agent/src/repair_agent/command.py"
|
|
41
|
+
validator = r"C:\repo\validator-agent\src\validator_agent\command.py"
|
|
42
|
+
|
|
43
|
+
assert is_intentional_duplicate_pair(doctor, repair)
|
|
44
|
+
assert is_intentional_duplicate_pair(repair, validator)
|
|
45
|
+
assert not is_intentional_duplicate_pair(repair, repair)
|
|
46
|
+
assert not is_intentional_duplicate_pair(repair, "/repo/app/command.py")
|
|
47
|
+
|
|
48
|
+
|
|
32
49
|
def test_duplicate_groups_not_pair_count(tmp_path: Path) -> None:
|
|
33
50
|
project = tmp_path
|
|
34
51
|
result = AnalysisResult(project_path=str(project))
|
|
@@ -78,3 +95,46 @@ def test_examples_dir_excluded_from_duplicate_pairs(tmp_path: Path) -> None:
|
|
|
78
95
|
|
|
79
96
|
dupes = DuplicatesMetricsComputer(str(project)).detect_duplicates(result)
|
|
80
97
|
assert dupes == []
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_cross_agent_duplicates_are_excluded_but_same_agent_duplicates_remain(
|
|
101
|
+
tmp_path: Path,
|
|
102
|
+
) -> None:
|
|
103
|
+
result = AnalysisResult(project_path=str(tmp_path))
|
|
104
|
+
paths = {
|
|
105
|
+
"doctor.main": tmp_path / "doctor-agent/src/main.py",
|
|
106
|
+
"doctor.legacy": tmp_path / "doctor-agent/src/legacy.py",
|
|
107
|
+
"repair.main": tmp_path / "repair-agent/src/main.py",
|
|
108
|
+
"validator.main": tmp_path / "validator-agent/src/main.py",
|
|
109
|
+
}
|
|
110
|
+
for pkg, path in paths.items():
|
|
111
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
112
|
+
path.write_text("# stub\n", encoding="utf-8")
|
|
113
|
+
result.classes[f"{pkg}.Worker"] = _worker(path, pkg)
|
|
114
|
+
|
|
115
|
+
dupes = DuplicatesMetricsComputer(str(tmp_path)).detect_duplicates(result)
|
|
116
|
+
|
|
117
|
+
assert len(dupes) == 1
|
|
118
|
+
assert dupes[0]["fileA"] == "doctor-agent/src/main.py"
|
|
119
|
+
assert dupes[0]["fileB"] == "doctor-agent/src/legacy.py"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_cross_agent_duplicates_do_not_create_planfile_ticket(tmp_path: Path) -> None:
|
|
123
|
+
result = AnalysisResult(project_path=str(tmp_path))
|
|
124
|
+
for repo, pkg in (
|
|
125
|
+
("doctor-agent", "doctor"),
|
|
126
|
+
("repair-agent", "repair"),
|
|
127
|
+
("validator-agent", "validator"),
|
|
128
|
+
):
|
|
129
|
+
path = tmp_path / repo / "src/command.py"
|
|
130
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
131
|
+
path.write_text("# stub\n", encoding="utf-8")
|
|
132
|
+
result.classes[f"{pkg}.Worker"] = _worker(path, pkg)
|
|
133
|
+
|
|
134
|
+
tickets = [
|
|
135
|
+
ticket
|
|
136
|
+
for ticket in collect_planfile_tickets(result)
|
|
137
|
+
if ticket.signal == "code2llm_dup"
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
assert tickets == []
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from types import SimpleNamespace
|
|
2
|
+
|
|
3
|
+
from code2llm.cli_exports.orchestrator import _build_export_config
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _args(**overrides):
|
|
7
|
+
values = {
|
|
8
|
+
"mode": "hybrid",
|
|
9
|
+
"strategy": None,
|
|
10
|
+
"exclude": [],
|
|
11
|
+
"gitignore": True,
|
|
12
|
+
}
|
|
13
|
+
values.update(overrides)
|
|
14
|
+
return SimpleNamespace(**values)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_export_cache_key_inputs_include_scan_profile():
|
|
18
|
+
full = _build_export_config(_args(), ["map"])
|
|
19
|
+
scoped = _build_export_config(
|
|
20
|
+
_args(mode="static", strategy="quick", exclude=["plugins", "*.md"]),
|
|
21
|
+
["map"],
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
assert full["mode"] == "hybrid"
|
|
25
|
+
assert scoped["mode"] == "static"
|
|
26
|
+
assert scoped["strategy"] == "quick"
|
|
27
|
+
assert scoped["exclude"] == ["*.md", "plugins"]
|
|
28
|
+
assert full != scoped
|
|
@@ -280,6 +280,9 @@ class TestProjectMap:
|
|
|
280
280
|
assert "etl.py" in map_content
|
|
281
281
|
assert "utils.py" in map_content
|
|
282
282
|
|
|
283
|
+
def test_declares_code2llm_as_canonical_producer(self, map_content):
|
|
284
|
+
assert "# producer: code2llm | artifact: map.toon.yaml | schema: 1" in map_content
|
|
285
|
+
|
|
283
286
|
def test_has_import_info(self, map_content):
|
|
284
287
|
assert "i:" in map_content or "import" in map_content.lower()
|
|
285
288
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from code2llm.generators.mermaid import png
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_find_browser_executable_prefers_puppeteer_environment(monkeypatch, tmp_path):
|
|
7
|
+
browser = tmp_path / "chrome"
|
|
8
|
+
browser.write_text("#!/bin/sh\n", encoding="utf-8")
|
|
9
|
+
browser.chmod(0o755)
|
|
10
|
+
monkeypatch.setenv("PUPPETEER_EXECUTABLE_PATH", str(browser))
|
|
11
|
+
monkeypatch.setattr(png.shutil, "which", lambda _command: None)
|
|
12
|
+
|
|
13
|
+
assert png._find_browser_executable() == str(browser)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_puppeteer_config_uses_detected_system_browser(monkeypatch):
|
|
17
|
+
monkeypatch.setattr(png, "_find_browser_executable", lambda: "/usr/bin/google-chrome")
|
|
18
|
+
|
|
19
|
+
_max_text_size, _max_edges, cfg_path, puppeteer_cfg_path = png._setup_puppeteer_config()
|
|
20
|
+
try:
|
|
21
|
+
assert cfg_path is not None
|
|
22
|
+
assert puppeteer_cfg_path is not None
|
|
23
|
+
config = json.loads(open(puppeteer_cfg_path, encoding="utf-8").read())
|
|
24
|
+
assert config["executablePath"] == "/usr/bin/google-chrome"
|
|
25
|
+
assert "--no-sandbox" in config["args"]
|
|
26
|
+
finally:
|
|
27
|
+
for path in (cfg_path, puppeteer_cfg_path):
|
|
28
|
+
if path:
|
|
29
|
+
png.os.unlink(path)
|
code2llm-0.5.174/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.5.174
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|