code2llm 0.5.169__tar.gz → 0.5.172__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.169/code2llm.egg-info → code2llm-0.5.172}/PKG-INFO +9 -6
- {code2llm-0.5.169 → code2llm-0.5.172}/README.md +5 -3
- code2llm-0.5.172/VERSION +1 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/__init__.py +1 -1
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/smells.py +26 -8
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/file_filter.py +0 -5
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/nlp/__init__.py +1 -1
- {code2llm-0.5.169 → code2llm-0.5.172/code2llm.egg-info}/PKG-INFO +9 -6
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm.egg-info/SOURCES.txt +1 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm.egg-info/requires.txt +1 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/pyproject.toml +4 -5
- {code2llm-0.5.169 → code2llm-0.5.172}/setup.py +2 -2
- code2llm-0.5.172/tests/test_smells_shotgun_surgery.py +97 -0
- code2llm-0.5.169/VERSION +0 -1
- {code2llm-0.5.169 → code2llm-0.5.172}/LICENSE +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/MANIFEST.in +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/__main__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/_data_impl.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/call_graph.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/cfg.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/coupling.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/data_analysis.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/dfg.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/pipeline_classifier.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/pipeline_detector.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/pipeline_resolver.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/side_effects.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/type_inference.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/utils/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/analysis/utils/ast_helpers.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/api.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_analysis.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_commands.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_exports/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_exports/code2logic.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_exports/formats.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_exports/orchestrator.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_exports/orchestrator_chunked.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_exports/orchestrator_constants.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_exports/orchestrator_handlers.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_exports/prompt.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/cli_parser.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/analyzer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/ast_registry.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/config.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/export_pipeline.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/file_analyzer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/file_cache.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/gitignore.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/incremental.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/_c_parser.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/_calls.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/_complexity.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/base.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/cpp.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/csharp.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/generic.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/go_lang.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/java.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/php.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/ruby.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/rust.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/ts_extractors.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/ts_parser.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/lang/typescript.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/large_repo.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/models.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/persistent_cache.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/refactoring.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/repo_files.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/source_classifier.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/streaming/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/streaming/cache.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/streaming/incremental.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/streaming/prioritizer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/streaming/scanner.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/streaming/strategies.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/streaming_analyzer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/core/toon_size_manager.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/article_view.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/base.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/context_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/context_view.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/dashboard_data.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/dashboard_renderer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/evolution/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/evolution/computation.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/evolution/constants.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/evolution/exclusion.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/evolution/render.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/evolution/yaml_export.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/evolution_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/flow_constants.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/flow_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/flow_renderer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/html_dashboard.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/index_generator/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/index_generator/renderer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/index_generator/scanner.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/index_generator.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/json_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/llm_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/map/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/map/alerts.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/map/details.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/map/header.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/map/module_list.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/map/utils.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/map/yaml_export.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/map_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid/calls.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid/classic.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid/compact.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid/flow_compact.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid/flow_detailed.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid/flow_full.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid/utils.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/planfile_tickets.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/project_yaml/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/project_yaml/constants.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/project_yaml/core.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/project_yaml/evolution.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/project_yaml/health.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/project_yaml/hotspots.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/project_yaml/modules.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/project_yaml_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/readme/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/readme/content.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/readme/files.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/readme/insights.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/readme/sections.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/readme_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/report_generators.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/_render_coupling_helpers.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/_render_section_helpers.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/constants.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/helpers.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/metrics.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/metrics_core.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/metrics_duplicates.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/metrics_health.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/module_detail.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon/renderer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/toon_view.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/validate_project.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/exporters/yaml_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/_utils.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_flow/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_flow/analysis.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_flow/cli.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_flow/generator.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_flow/nodes.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_flow/parsing.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_flow/utils.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_flow.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/llm_task.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/mermaid/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/mermaid/fix.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/mermaid/png.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/mermaid/validation.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/generators/mermaid.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/nlp/config.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/nlp/entity_resolution.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/nlp/intent_matching.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/nlp/normalization.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/nlp/pipeline.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/parsers/toon_parser.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/patterns/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/patterns/detector.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/refactor/__init__.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm/refactor/prompt_engine.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm.egg-info/dependency_links.txt +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm.egg-info/entry_points.txt +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/code2llm.egg-info/top_level.txt +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/setup.cfg +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_advanced_analysis.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_analyzer.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_cache_invalidation_e2e.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_calls_toon_export.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_declarative_collection.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_deep_analysis.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_edge_cases.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_export_cache_flags.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_file_analyzer_tagging.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_flow_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_format_quality.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_multilanguage_e2e.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_nlp_pipeline.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_nonpython_cc_calls.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_orchestrator_cache_mtime.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_persistent_cache.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_pipeline_detector.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_planfile_tickets_exporter.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_project_toon_export.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_prompt_engine.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_prompt_txt.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_refactoring_engine.py +0 -0
- {code2llm-0.5.169 → code2llm-0.5.172}/tests/test_toon_v2.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.172
|
|
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
|
-
Author:
|
|
6
|
+
Author: Tom Sapletta
|
|
7
7
|
Author-email: Tom Sapletta <tom@sapletta.com>
|
|
8
|
-
License: Apache-2.0
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
9
|
Project-URL: Homepage, https://github.com/wronai/stts
|
|
10
10
|
Project-URL: Repository, https://github.com/wronai/stts
|
|
11
11
|
Project-URL: Issues, https://github.com/wronai/stts/issues
|
|
@@ -32,6 +32,7 @@ Requires-Dist: numpy>=1.20
|
|
|
32
32
|
Requires-Dist: jinja2>=3.0
|
|
33
33
|
Requires-Dist: radon>=5.1
|
|
34
34
|
Requires-Dist: astroid>=3.0
|
|
35
|
+
Requires-Dist: psutil>=5.9
|
|
35
36
|
Requires-Dist: code2logic
|
|
36
37
|
Requires-Dist: vulture>=2.10
|
|
37
38
|
Requires-Dist: tiktoken>=0.5
|
|
@@ -66,11 +67,13 @@ Dynamic: requires-python
|
|
|
66
67
|
|
|
67
68
|
## AI Cost Tracking
|
|
68
69
|
|
|
69
|
-
   
|
|
71
|
+
  
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
- 🤖 **LLM usage:** $17.3260 (246 commits)
|
|
74
|
+
- 👤 **Human dev:** ~$9280 (92.8h @ $100/h, 30min dedup)
|
|
72
75
|
|
|
73
|
-
Generated on 2026-06
|
|
76
|
+
Generated on 2026-07-06 using [openrouter/deep/deep-v4-pro](https://openrouter.ai/deep/deep-v4-pro)
|
|
74
77
|
|
|
75
78
|
---
|
|
76
79
|
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## AI Cost Tracking
|
|
4
4
|
|
|
5
|
-
   
|
|
6
|
+
  
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
- 🤖 **LLM usage:** $17.3260 (246 commits)
|
|
9
|
+
- 👤 **Human dev:** ~$9280 (92.8h @ $100/h, 30min dedup)
|
|
8
10
|
|
|
9
|
-
Generated on 2026-06
|
|
11
|
+
Generated on 2026-07-06 using [openrouter/deep/deep-v4-pro](https://openrouter.ai/deep/deep-v4-pro)
|
|
10
12
|
|
|
11
13
|
---
|
|
12
14
|
|
code2llm-0.5.172/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.5.172
|
|
@@ -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.172"
|
|
12
12
|
__author__ = "STTS Project"
|
|
13
13
|
|
|
14
14
|
# Core analysis components (lightweight, always needed)
|
|
@@ -163,16 +163,33 @@ class SmellDetector:
|
|
|
163
163
|
return smells
|
|
164
164
|
|
|
165
165
|
def _detect_shotgun_surgery(self) -> List[CodeSmell]:
|
|
166
|
-
"""Detect variables whose mutation requires changes across many functions.
|
|
166
|
+
"""Detect variables whose mutation requires changes across many functions.
|
|
167
|
+
|
|
168
|
+
Grouped by (file, variable), not variable name alone: a generic local
|
|
169
|
+
name like `args`, `data`, or `client` is conventionally reused as an
|
|
170
|
+
independent local in unrelated functions across unrelated files/
|
|
171
|
+
packages (every argparse `main()` has an `args`) -- that's naming
|
|
172
|
+
coincidence, not a variable whose logic is genuinely coupled across
|
|
173
|
+
call sites. Grouping by bare name alone falsely flagged every such
|
|
174
|
+
coincidence as "shotgun surgery" (reproduced: 40+ false-positive
|
|
175
|
+
tickets in a single monorepo, e.g. `args` in a 40-line, one-function
|
|
176
|
+
CLI file reported as "spans 8 functions" -- the other 7 were
|
|
177
|
+
unrelated `args` locals in unrelated files elsewhere in the tree).
|
|
178
|
+
Real shotgun surgery -- one variable/attribute whose change genuinely
|
|
179
|
+
ripples across many functions -- is a same-file (or same-class)
|
|
180
|
+
phenomenon; scoping by file preserves that signal while dropping the
|
|
181
|
+
cross-file name-collision noise.
|
|
182
|
+
"""
|
|
167
183
|
smells = []
|
|
168
|
-
var_mutators = {} # variable -> set(functions)
|
|
184
|
+
var_mutators = {} # (file, variable) -> set(functions)
|
|
169
185
|
|
|
170
186
|
for mutation in self.result.mutations:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
187
|
+
key = (mutation.file, mutation.variable)
|
|
188
|
+
if key not in var_mutators:
|
|
189
|
+
var_mutators[key] = set()
|
|
190
|
+
var_mutators[key].add(mutation.scope)
|
|
174
191
|
|
|
175
|
-
for var, funcs in var_mutators.items():
|
|
192
|
+
for (file, var), funcs in var_mutators.items():
|
|
176
193
|
if len(funcs) >= 5:
|
|
177
194
|
# Find a representative function to report the smell
|
|
178
195
|
func_name = list(funcs)[0]
|
|
@@ -188,10 +205,11 @@ class SmellDetector:
|
|
|
188
205
|
line=func_info.line,
|
|
189
206
|
severity=0.8,
|
|
190
207
|
description=(
|
|
191
|
-
f"Mutation of variable '{var}' spans {len(funcs)} functions
|
|
208
|
+
f"Mutation of variable '{var}' spans {len(funcs)} functions"
|
|
209
|
+
f" in {file}."
|
|
192
210
|
" Changing this logic requires work in many places."
|
|
193
211
|
),
|
|
194
|
-
context={"variable": var, "affected_functions": list(funcs)},
|
|
212
|
+
context={"variable": var, "file": file, "affected_functions": list(funcs)},
|
|
195
213
|
)
|
|
196
214
|
)
|
|
197
215
|
return smells
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.172
|
|
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
|
-
Author:
|
|
6
|
+
Author: Tom Sapletta
|
|
7
7
|
Author-email: Tom Sapletta <tom@sapletta.com>
|
|
8
|
-
License: Apache-2.0
|
|
8
|
+
License-Expression: Apache-2.0
|
|
9
9
|
Project-URL: Homepage, https://github.com/wronai/stts
|
|
10
10
|
Project-URL: Repository, https://github.com/wronai/stts
|
|
11
11
|
Project-URL: Issues, https://github.com/wronai/stts/issues
|
|
@@ -32,6 +32,7 @@ Requires-Dist: numpy>=1.20
|
|
|
32
32
|
Requires-Dist: jinja2>=3.0
|
|
33
33
|
Requires-Dist: radon>=5.1
|
|
34
34
|
Requires-Dist: astroid>=3.0
|
|
35
|
+
Requires-Dist: psutil>=5.9
|
|
35
36
|
Requires-Dist: code2logic
|
|
36
37
|
Requires-Dist: vulture>=2.10
|
|
37
38
|
Requires-Dist: tiktoken>=0.5
|
|
@@ -66,11 +67,13 @@ Dynamic: requires-python
|
|
|
66
67
|
|
|
67
68
|
## AI Cost Tracking
|
|
68
69
|
|
|
69
|
-
   
|
|
71
|
+
  
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
- 🤖 **LLM usage:** $17.3260 (246 commits)
|
|
74
|
+
- 👤 **Human dev:** ~$9280 (92.8h @ $100/h, 30min dedup)
|
|
72
75
|
|
|
73
|
-
Generated on 2026-06
|
|
76
|
+
Generated on 2026-07-06 using [openrouter/deep/deep-v4-pro](https://openrouter.ai/deep/deep-v4-pro)
|
|
74
77
|
|
|
75
78
|
---
|
|
76
79
|
|
|
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code2llm"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.172"
|
|
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
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
11
|
authors = [
|
|
12
12
|
{name = "Tom Sapletta", email = "tom@sapletta.com"},
|
|
13
13
|
]
|
|
@@ -45,6 +45,7 @@ dependencies = [
|
|
|
45
45
|
"jinja2>=3.0",
|
|
46
46
|
"radon>=5.1",
|
|
47
47
|
"astroid>=3.0",
|
|
48
|
+
"psutil>=5.9",
|
|
48
49
|
"code2logic",
|
|
49
50
|
"vulture>=2.10",
|
|
50
51
|
"tiktoken>=0.5",
|
|
@@ -62,9 +63,7 @@ dependencies = [
|
|
|
62
63
|
"tree-sitter-ruby>=0.21",
|
|
63
64
|
]
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
text = "Apache-2.0"
|
|
67
|
-
|
|
66
|
+
license = "Apache-2.0"
|
|
68
67
|
[project.optional-dependencies]
|
|
69
68
|
dev = [
|
|
70
69
|
"pytest>=6.2",
|
|
@@ -29,8 +29,8 @@ setup(
|
|
|
29
29
|
description="Python code flow analysis tool - CFG, DFG, and call graph extraction",
|
|
30
30
|
long_description=read_readme(),
|
|
31
31
|
long_description_content_type="text/markdown",
|
|
32
|
-
author="
|
|
33
|
-
author_email="",
|
|
32
|
+
author="Tom Sapletta",
|
|
33
|
+
author_email="tom@sapletta.com",
|
|
34
34
|
url="https://github.com/wronai/stts",
|
|
35
35
|
packages=find_packages(),
|
|
36
36
|
entry_points={
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Tests for SmellDetector._detect_shotgun_surgery.
|
|
2
|
+
|
|
3
|
+
2026-07-06 incident: grouping mutations by variable *name* alone (ignoring
|
|
4
|
+
file) meant a generic local name like `args`/`data`/`client` -- conventionally
|
|
5
|
+
reused as an independent local in unrelated functions across unrelated
|
|
6
|
+
files -- falsely triggered "Shotgun Surgery" whenever 5+ unrelated functions
|
|
7
|
+
anywhere in the analyzed tree happened to share that name. Reproduced live:
|
|
8
|
+
40+ false-positive tickets in one monorepo, including `args` in a 40-line,
|
|
9
|
+
one-function CLI file reported as "spans 8 functions" (the other 7 were
|
|
10
|
+
unrelated `args` locals in unrelated files elsewhere in the tree).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from code2llm.analysis.smells import SmellDetector
|
|
16
|
+
from code2llm.core.models import AnalysisResult, FunctionInfo, Mutation
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _function(name: str, file: str, line: int = 1) -> FunctionInfo:
|
|
20
|
+
return FunctionInfo(name=name, qualified_name=f"{file}::{name}", file=file, line=line)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _mutation(variable: str, file: str, scope: str, line: int = 1) -> Mutation:
|
|
24
|
+
return Mutation(
|
|
25
|
+
variable=variable, file=file, line=line, type="assign", scope=scope, context=""
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_same_name_across_unrelated_files_is_not_shotgun_surgery():
|
|
30
|
+
"""The core regression: `args` reused independently in 6 unrelated
|
|
31
|
+
files/functions must NOT be flagged -- no single file has more than one
|
|
32
|
+
mutating function."""
|
|
33
|
+
result = AnalysisResult()
|
|
34
|
+
for i in range(6):
|
|
35
|
+
file = f"pkg{i}/cli.py"
|
|
36
|
+
scope = f"pkg{i}.cli::main"
|
|
37
|
+
result.functions[scope] = _function("main", file)
|
|
38
|
+
result.mutations.append(_mutation("args", file, scope))
|
|
39
|
+
|
|
40
|
+
smells = SmellDetector(result)._detect_shotgun_surgery()
|
|
41
|
+
|
|
42
|
+
assert smells == []
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_genuine_same_file_shotgun_surgery_still_detected():
|
|
46
|
+
"""5+ functions *within the same file* mutating the same variable is the
|
|
47
|
+
real smell and must still be caught."""
|
|
48
|
+
result = AnalysisResult()
|
|
49
|
+
file = "core/session.py"
|
|
50
|
+
for i in range(5):
|
|
51
|
+
scope = f"core.session::step_{i}"
|
|
52
|
+
result.functions[scope] = _function(f"step_{i}", file, line=10 * i)
|
|
53
|
+
result.mutations.append(_mutation("state", file, scope))
|
|
54
|
+
|
|
55
|
+
smells = SmellDetector(result)._detect_shotgun_surgery()
|
|
56
|
+
|
|
57
|
+
assert len(smells) == 1
|
|
58
|
+
assert smells[0].name == "Shotgun Surgery: state"
|
|
59
|
+
assert set(smells[0].context["affected_functions"]) == {
|
|
60
|
+
f"core.session::step_{i}" for i in range(5)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_four_functions_in_one_file_below_threshold():
|
|
65
|
+
result = AnalysisResult()
|
|
66
|
+
file = "core/session.py"
|
|
67
|
+
for i in range(4):
|
|
68
|
+
scope = f"core.session::step_{i}"
|
|
69
|
+
result.functions[scope] = _function(f"step_{i}", file)
|
|
70
|
+
result.mutations.append(_mutation("state", file, scope))
|
|
71
|
+
|
|
72
|
+
smells = SmellDetector(result)._detect_shotgun_surgery()
|
|
73
|
+
|
|
74
|
+
assert smells == []
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_same_variable_name_in_two_files_counts_separately_per_file():
|
|
78
|
+
"""5 mutators of 'data' in file A (real smell) plus unrelated mutators of
|
|
79
|
+
'data' in file B must not combine into a bigger, less accurate count,
|
|
80
|
+
and file B (below threshold) must not itself be flagged."""
|
|
81
|
+
result = AnalysisResult()
|
|
82
|
+
file_a = "a.py"
|
|
83
|
+
for i in range(5):
|
|
84
|
+
scope = f"a::fn_{i}"
|
|
85
|
+
result.functions[scope] = _function(f"fn_{i}", file_a)
|
|
86
|
+
result.mutations.append(_mutation("data", file_a, scope))
|
|
87
|
+
|
|
88
|
+
file_b = "b.py"
|
|
89
|
+
for i in range(3):
|
|
90
|
+
scope = f"b::fn_{i}"
|
|
91
|
+
result.functions[scope] = _function(f"fn_{i}", file_b)
|
|
92
|
+
result.mutations.append(_mutation("data", file_b, scope))
|
|
93
|
+
|
|
94
|
+
smells = SmellDetector(result)._detect_shotgun_surgery()
|
|
95
|
+
|
|
96
|
+
assert len(smells) == 1
|
|
97
|
+
assert smells[0].context["file"] == file_a
|
code2llm-0.5.169/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.5.169
|
|
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
|
|
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
|
|
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
|
|
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
|