code2llm 0.5.144__tar.gz → 0.5.145__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. {code2llm-0.5.144/code2llm.egg-info → code2llm-0.5.145}/PKG-INFO +12 -12
  2. {code2llm-0.5.144 → code2llm-0.5.145}/README.md +9 -9
  3. code2llm-0.5.145/VERSION +1 -0
  4. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/__init__.py +1 -1
  5. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_analysis.py +14 -0
  6. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_parser.py +6 -0
  7. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/__init__.py +2 -2
  8. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/analyzer.py +47 -28
  9. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/config.py +14 -0
  10. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/file_analyzer.py +11 -4
  11. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/persistent_cache.py +50 -32
  12. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/refactoring.py +21 -7
  13. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/__init__.py +1 -1
  14. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/incremental.py +11 -11
  15. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming_analyzer.py +2 -2
  16. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_task.py +44 -34
  17. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/__init__.py +1 -1
  18. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/pipeline.py +8 -8
  19. {code2llm-0.5.144 → code2llm-0.5.145/code2llm.egg-info}/PKG-INFO +12 -12
  20. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/requires.txt +1 -1
  21. {code2llm-0.5.144 → code2llm-0.5.145}/pyproject.toml +5 -3
  22. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_deep_analysis.py +1 -0
  23. code2llm-0.5.144/VERSION +0 -1
  24. {code2llm-0.5.144 → code2llm-0.5.145}/LICENSE +0 -0
  25. {code2llm-0.5.144 → code2llm-0.5.145}/MANIFEST.in +0 -0
  26. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/__main__.py +0 -0
  27. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/__init__.py +0 -0
  28. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/call_graph.py +0 -0
  29. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/cfg.py +0 -0
  30. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/coupling.py +0 -0
  31. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/data_analysis.py +0 -0
  32. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/dfg.py +0 -0
  33. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/pipeline_classifier.py +0 -0
  34. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/pipeline_detector.py +0 -0
  35. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/pipeline_resolver.py +0 -0
  36. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/side_effects.py +0 -0
  37. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/smells.py +0 -0
  38. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/type_inference.py +0 -0
  39. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/utils/__init__.py +0 -0
  40. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/utils/ast_helpers.py +0 -0
  41. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/api.py +0 -0
  42. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli.py +0 -0
  43. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_commands.py +0 -0
  44. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/__init__.py +0 -0
  45. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/code2logic.py +0 -0
  46. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/formats.py +0 -0
  47. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/orchestrator.py +0 -0
  48. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/orchestrator_chunked.py +0 -0
  49. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/orchestrator_constants.py +0 -0
  50. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/orchestrator_handlers.py +0 -0
  51. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/prompt.py +0 -0
  52. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/ast_registry.py +0 -0
  53. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/export_pipeline.py +0 -0
  54. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/file_cache.py +0 -0
  55. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/file_filter.py +0 -0
  56. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/gitignore.py +0 -0
  57. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/incremental.py +0 -0
  58. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/__init__.py +0 -0
  59. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/base.py +0 -0
  60. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/cpp.py +0 -0
  61. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/csharp.py +0 -0
  62. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/generic.py +0 -0
  63. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/go_lang.py +0 -0
  64. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/java.py +0 -0
  65. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/php.py +0 -0
  66. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/ruby.py +0 -0
  67. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/rust.py +0 -0
  68. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/ts_extractors.py +0 -0
  69. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/ts_parser.py +0 -0
  70. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/typescript.py +0 -0
  71. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/large_repo.py +0 -0
  72. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/models.py +0 -0
  73. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/repo_files.py +0 -0
  74. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/cache.py +0 -0
  75. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/prioritizer.py +0 -0
  76. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/scanner.py +0 -0
  77. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/strategies.py +0 -0
  78. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/toon_size_manager.py +0 -0
  79. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/__init__.py +0 -0
  80. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/article_view.py +0 -0
  81. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/base.py +0 -0
  82. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/context_exporter.py +0 -0
  83. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/context_view.py +0 -0
  84. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/dashboard_data.py +0 -0
  85. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/dashboard_renderer.py +0 -0
  86. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/__init__.py +0 -0
  87. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/computation.py +0 -0
  88. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/constants.py +0 -0
  89. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/exclusion.py +0 -0
  90. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/render.py +0 -0
  91. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/yaml_export.py +0 -0
  92. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution_exporter.py +0 -0
  93. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/flow_constants.py +0 -0
  94. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/flow_exporter.py +0 -0
  95. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/flow_renderer.py +0 -0
  96. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/html_dashboard.py +0 -0
  97. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/index_generator/__init__.py +0 -0
  98. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/index_generator/renderer.py +0 -0
  99. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/index_generator/scanner.py +0 -0
  100. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/index_generator.py +0 -0
  101. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/json_exporter.py +0 -0
  102. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/llm_exporter.py +0 -0
  103. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/__init__.py +0 -0
  104. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/alerts.py +0 -0
  105. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/details.py +0 -0
  106. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/header.py +0 -0
  107. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/module_list.py +0 -0
  108. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/utils.py +0 -0
  109. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/yaml_export.py +0 -0
  110. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map_exporter.py +0 -0
  111. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/__init__.py +0 -0
  112. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/calls.py +0 -0
  113. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/classic.py +0 -0
  114. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/compact.py +0 -0
  115. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/flow_compact.py +0 -0
  116. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/flow_detailed.py +0 -0
  117. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/flow_full.py +0 -0
  118. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/utils.py +0 -0
  119. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid_exporter.py +0 -0
  120. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
  121. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/__init__.py +0 -0
  122. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/constants.py +0 -0
  123. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/core.py +0 -0
  124. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/evolution.py +0 -0
  125. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/health.py +0 -0
  126. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/hotspots.py +0 -0
  127. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/modules.py +0 -0
  128. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml_exporter.py +0 -0
  129. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/__init__.py +0 -0
  130. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/content.py +0 -0
  131. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/files.py +0 -0
  132. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/insights.py +0 -0
  133. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/sections.py +0 -0
  134. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme_exporter.py +0 -0
  135. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/report_generators.py +0 -0
  136. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/__init__.py +0 -0
  137. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/helpers.py +0 -0
  138. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/metrics.py +0 -0
  139. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/metrics_core.py +0 -0
  140. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/metrics_duplicates.py +0 -0
  141. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/metrics_health.py +0 -0
  142. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/module_detail.py +0 -0
  143. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/renderer.py +0 -0
  144. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon.py +0 -0
  145. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon_view.py +0 -0
  146. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/validate_project.py +0 -0
  147. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/yaml_exporter.py +0 -0
  148. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/__init__.py +0 -0
  149. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/_utils.py +0 -0
  150. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/__init__.py +0 -0
  151. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/analysis.py +0 -0
  152. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/cli.py +0 -0
  153. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/generator.py +0 -0
  154. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/nodes.py +0 -0
  155. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/parsing.py +0 -0
  156. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/utils.py +0 -0
  157. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow.py +0 -0
  158. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid/__init__.py +0 -0
  159. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid/fix.py +0 -0
  160. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid/png.py +0 -0
  161. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid/validation.py +0 -0
  162. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid.py +0 -0
  163. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/config.py +0 -0
  164. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/entity_resolution.py +0 -0
  165. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/intent_matching.py +0 -0
  166. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/normalization.py +0 -0
  167. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/parsers/toon_parser.py +0 -0
  168. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/patterns/__init__.py +0 -0
  169. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/patterns/detector.py +0 -0
  170. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/refactor/__init__.py +0 -0
  171. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/refactor/prompt_engine.py +0 -0
  172. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/SOURCES.txt +0 -0
  173. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/dependency_links.txt +0 -0
  174. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/entry_points.txt +0 -0
  175. {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/top_level.txt +0 -0
  176. {code2llm-0.5.144 → code2llm-0.5.145}/setup.cfg +0 -0
  177. {code2llm-0.5.144 → code2llm-0.5.145}/setup.py +0 -0
  178. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_advanced_analysis.py +0 -0
  179. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_analyzer.py +0 -0
  180. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_cache_invalidation_e2e.py +0 -0
  181. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_calls_toon_export.py +0 -0
  182. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_declarative_collection.py +0 -0
  183. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_edge_cases.py +0 -0
  184. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_file_analyzer_tagging.py +0 -0
  185. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_flow_exporter.py +0 -0
  186. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_format_quality.py +0 -0
  187. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_multilanguage_e2e.py +0 -0
  188. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_nlp_pipeline.py +0 -0
  189. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_nonpython_cc_calls.py +0 -0
  190. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_orchestrator_cache_mtime.py +0 -0
  191. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_persistent_cache.py +0 -0
  192. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_pipeline_detector.py +0 -0
  193. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_project_toon_export.py +0 -0
  194. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_prompt_engine.py +0 -0
  195. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_prompt_txt.py +0 -0
  196. {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_refactoring_engine.py +0 -0
  197. {code2llm-0.5.144 → code2llm-0.5.145}/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.144
3
+ Version: 0.5.145
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: STTS Project
7
7
  Author-email: Tom Sapletta <tom@sapletta.com>
8
- License-Expression: Apache-2.0
8
+ License: 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
@@ -54,7 +54,7 @@ Requires-Dist: pytest-xdist>=3.0; extra == "dev"
54
54
  Requires-Dist: black>=21.0; extra == "dev"
55
55
  Requires-Dist: flake8>=3.9; extra == "dev"
56
56
  Requires-Dist: mypy>=0.910; extra == "dev"
57
- Requires-Dist: goal>=2.1.0; extra == "dev"
57
+ Requires-Dist: goal>=2.1.218; extra == "dev"
58
58
  Requires-Dist: costs>=0.1.20; extra == "dev"
59
59
  Requires-Dist: pfix>=0.1.60; extra == "dev"
60
60
  Dynamic: author
@@ -67,13 +67,13 @@ Dynamic: requires-python
67
67
 
68
68
  ## AI Cost Tracking
69
69
 
70
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.144-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
71
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-70.2h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
70
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.145-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
71
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-71.2h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
72
72
 
73
- - 🤖 **LLM usage:** $7.5000 (196 commits)
74
- - 👤 **Human dev:** ~$7024 (70.2h @ $100/h, 30min dedup)
73
+ - 🤖 **LLM usage:** $7.5000 (197 commits)
74
+ - 👤 **Human dev:** ~$7124 (71.2h @ $100/h, 30min dedup)
75
75
 
76
- Generated on 2026-04-25 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
76
+ Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
77
77
 
78
78
  ---
79
79
 
@@ -407,10 +407,10 @@ code2llm ./ -f yaml --separate-orphans
407
407
  ---
408
408
 
409
409
  **Generated by**: `code2llm ./ -f all --readme`
410
- **Analysis Date**: 2026-04-25
411
- **Total Functions**: 3085
412
- **Total Classes**: 259
413
- **Modules**: 498
410
+ **Analysis Date**: 2026-05-06
411
+ **Total Functions**: 3625
412
+ **Total Classes**: 250
413
+ **Modules**: 492
414
414
 
415
415
  For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
416
416
 
@@ -3,13 +3,13 @@
3
3
 
4
4
  ## AI Cost Tracking
5
5
 
6
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.144-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-70.2h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
6
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.145-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-71.2h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
8
8
 
9
- - 🤖 **LLM usage:** $7.5000 (196 commits)
10
- - 👤 **Human dev:** ~$7024 (70.2h @ $100/h, 30min dedup)
9
+ - 🤖 **LLM usage:** $7.5000 (197 commits)
10
+ - 👤 **Human dev:** ~$7124 (71.2h @ $100/h, 30min dedup)
11
11
 
12
- Generated on 2026-04-25 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
12
+ Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
13
13
 
14
14
  ---
15
15
 
@@ -343,10 +343,10 @@ code2llm ./ -f yaml --separate-orphans
343
343
  ---
344
344
 
345
345
  **Generated by**: `code2llm ./ -f all --readme`
346
- **Analysis Date**: 2026-04-25
347
- **Total Functions**: 3085
348
- **Total Classes**: 259
349
- **Modules**: 498
346
+ **Analysis Date**: 2026-05-06
347
+ **Total Functions**: 3625
348
+ **Total Classes**: 250
349
+ **Modules**: 492
350
350
 
351
351
  For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
352
352
 
@@ -0,0 +1 @@
1
+ 0.5.145
@@ -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.144"
11
+ __version__ = "0.5.145"
12
12
  __author__ = "STTS Project"
13
13
 
14
14
  # Core analysis components (lightweight, always needed)
@@ -88,6 +88,20 @@ def _build_config(args, output_dir: Path):
88
88
  config.watch = getattr(args, 'watch', False)
89
89
  # Dry-run mode (handled in orchestrator, but stored for reference)
90
90
  config.dry_run = getattr(args, 'dry_run', False)
91
+
92
+ # --fast: skip expensive analyses (vulture, centrality, DFG, communities)
93
+ if getattr(args, 'fast', False):
94
+ config.performance.fast_mode = True
95
+ config.performance.apply_fast_mode()
96
+
97
+ # Strategy-based performance tuning
98
+ strategy = getattr(args, 'strategy', 'standard')
99
+ if strategy == 'quick':
100
+ config.performance.skip_data_flow = True
101
+ config.performance.skip_dead_code_detection = True
102
+ config.performance.skip_centrality = True
103
+ config.performance.skip_community_detection = True
104
+
91
105
  return config
92
106
 
93
107
 
@@ -159,6 +159,12 @@ Strategy Options (--strategy):
159
159
  help='Auto-detect changed files and only re-analyze those (faster subsequent runs)'
160
160
  )
161
161
 
162
+ parser.add_argument(
163
+ '--fast',
164
+ action='store_true',
165
+ help='Skip expensive analyses (vulture, centrality, DFG, communities) for faster runs'
166
+ )
167
+
162
168
  parser.add_argument(
163
169
  '--strategy',
164
170
  choices=['quick', 'standard', 'deep'],
@@ -9,7 +9,7 @@ from .models import (
9
9
  __all__ = [
10
10
  'ProjectAnalyzer',
11
11
  'StreamingAnalyzer',
12
- 'IncrementalAnalyzer',
12
+ 'StreamingIncrementalAnalyzer',
13
13
  'ScanStrategy',
14
14
  'SmartPrioritizer',
15
15
  'STRATEGY_QUICK',
@@ -43,7 +43,7 @@ def __getattr__(name):
43
43
  return locals()[name]
44
44
 
45
45
  _streaming_names = {
46
- 'StreamingAnalyzer', 'IncrementalAnalyzer', 'ScanStrategy',
46
+ 'StreamingAnalyzer', 'StreamingIncrementalAnalyzer', 'ScanStrategy',
47
47
  'SmartPrioritizer', 'STRATEGY_QUICK', 'STRATEGY_STANDARD', 'STRATEGY_DEEP',
48
48
  }
49
49
  if name in _streaming_names:
@@ -121,10 +121,16 @@ class ProjectAnalyzer:
121
121
  return None, [], files
122
122
 
123
123
  def _run_analysis(self, files_to_analyze: List[Tuple[str, str]]) -> List[Dict]:
124
- """Analyze files in parallel or sequentially depending on config."""
124
+ """Analyze files in parallel or sequentially depending on config.
125
+
126
+ Parallel mode has significant startup/pickle overhead. It is only
127
+ beneficial for larger file sets (threshold: 30 files).
128
+ """
125
129
  if not files_to_analyze:
126
130
  return []
127
- if self.config.performance.parallel_enabled and len(files_to_analyze) > 1:
131
+ _PARALLEL_THRESHOLD = 30
132
+ if (self.config.performance.parallel_enabled
133
+ and len(files_to_analyze) > _PARALLEL_THRESHOLD):
128
134
  return self._analyze_parallel(files_to_analyze)
129
135
  return self._analyze_sequential(files_to_analyze)
130
136
 
@@ -197,39 +203,61 @@ class ProjectAnalyzer:
197
203
  if self.config.verbose:
198
204
  self._print_summary(merged)
199
205
 
206
+ @staticmethod
207
+ def _should_collect_file(
208
+ filename: str,
209
+ ext_set: set,
210
+ filename_set_lower: frozenset,
211
+ filename_prefixes_lower: tuple,
212
+ ) -> bool:
213
+ """Return True if *filename* matches a known language extension,
214
+ well-known filename (Dockerfile, Makefile, ...), or filename prefix
215
+ (Dockerfile.dev, Makefile.am).
216
+ """
217
+ filename_lower = filename.lower()
218
+ suffix = os.path.splitext(filename)[1].lower()
219
+ return (
220
+ suffix in ext_set
221
+ or filename_lower in filename_set_lower
222
+ or filename_lower.startswith(filename_prefixes_lower)
223
+ )
224
+
225
+ @staticmethod
226
+ def _compute_module_name(
227
+ rel: str, filename: str, project_name: str
228
+ ) -> str:
229
+ """Derive a Pythonic module name from a relative file path."""
230
+ parts = rel.replace('\\', '/').split('/')
231
+ dir_parts = parts[:-1]
232
+ init_names = frozenset({'__init__.py', 'index.js', 'index.ts', 'mod.rs', 'lib.rs'})
233
+ if filename in init_names:
234
+ return '.'.join(dir_parts) if dir_parts else project_name
235
+ stem = os.path.splitext(filename)[0]
236
+ return '.'.join(dir_parts + [stem]) if dir_parts else stem
237
+
200
238
  def _collect_files(self, project_path: Path) -> List[Tuple[str, str]]:
201
239
  """Collect all source files with their module names for all supported languages.
202
-
240
+
203
241
  Uses a single os.walk traversal with early directory pruning instead of
204
242
  separate rglob calls per extension (~40x speedup on large repos).
205
243
  """
206
244
  files = []
207
- ext_set = set(ALL_EXTENSIONS) # O(1) lookup
208
- # Filename lookup uses a case-insensitive set. We lowercase once
209
- # here so the hot loop only does a single lower() per file.
245
+ ext_set = set(ALL_EXTENSIONS)
210
246
  filename_set_lower = frozenset(n.lower() for n in ALL_FILENAMES)
211
247
  filename_prefixes_lower = tuple(p.lower() for p in LANGUAGE_FILENAME_PREFIXES)
212
- init_names = frozenset({'__init__.py', 'index.js', 'index.ts', 'mod.rs', 'lib.rs'})
213
- seen = set() # guard against duplicate paths (e.g. .h in both c and cpp lists)
248
+ seen = set()
214
249
  project_str = str(project_path)
250
+ project_name = project_path.name
215
251
 
216
252
  for dirpath, dirnames, filenames in os.walk(project_str, topdown=True):
217
- # Prune skipped directories in-place so os.walk won't descend into them
218
253
  dirnames[:] = [
219
254
  d for d in dirnames
220
255
  if not self.file_filter.should_skip_dir(d)
221
256
  ]
222
257
 
223
258
  for filename in filenames:
224
- filename_lower = filename.lower()
225
- suffix = os.path.splitext(filename)[1].lower()
226
- # Accept by extension, well-known filename
227
- # (Dockerfile, Makefile, Jenkinsfile, ...), or known
228
- # prefix (Dockerfile.dev, Dockerfile.prod, Makefile.am).
229
- if (
230
- suffix not in ext_set
231
- and filename_lower not in filename_set_lower
232
- and not filename_lower.startswith(filename_prefixes_lower)
259
+ if not self._should_collect_file(
260
+ filename, ext_set, filename_set_lower, filename_prefixes_lower
233
261
  ):
234
262
  continue
235
263
 
@@ -241,17 +269,8 @@ class ProjectAnalyzer:
241
269
  if not self.file_filter.should_process(file_str):
242
270
  continue
243
271
 
244
- # Calculate module name from relative path
245
272
  rel = os.path.relpath(file_str, project_str)
246
- parts = rel.replace('\\', '/').split('/')
247
- dir_parts = parts[:-1] # everything before filename
248
-
249
- if filename in init_names:
250
- module_name = '.'.join(dir_parts) if dir_parts else project_path.name
251
- else:
252
- stem = os.path.splitext(filename)[0]
253
- module_name = '.'.join(dir_parts + [stem]) if dir_parts else stem
254
-
273
+ module_name = self._compute_module_name(rel, filename, project_name)
255
274
  files.append((file_str, module_name))
256
275
 
257
276
  return files
@@ -81,6 +81,10 @@ class PerformanceConfig:
81
81
  fast_mode: bool = False
82
82
  skip_data_flow: bool = False
83
83
  skip_pattern_detection: bool = False
84
+ skip_refactoring_analysis: bool = False
85
+ skip_dead_code_detection: bool = True
86
+ skip_centrality: bool = False
87
+ skip_community_detection: bool = False
84
88
 
85
89
  def get_workers(self) -> int:
86
90
  """Get effective worker count (auto-detect if set to 0)."""
@@ -88,6 +92,16 @@ class PerformanceConfig:
88
92
  return _get_optimal_workers(default=4)
89
93
  return self.parallel_workers
90
94
 
95
+ def apply_fast_mode(self) -> None:
96
+ """Apply fast_mode overrides — skip expensive analyses."""
97
+ if not self.fast_mode:
98
+ return
99
+ self.skip_data_flow = True
100
+ self.skip_pattern_detection = True
101
+ self.skip_dead_code_detection = True
102
+ self.skip_centrality = True
103
+ self.skip_community_detection = True
104
+
91
105
 
92
106
  @dataclass
93
107
  class FilterConfig:
@@ -124,8 +124,9 @@ class FileAnalyzer:
124
124
  # Calculate complexity with radon
125
125
  self._calculate_complexity(content, file_path, result)
126
126
 
127
- # Deep Analysis for refactoring
128
- self._perform_deep_analysis(tree, module_name, file_path, result)
127
+ # Deep Analysis for refactoring (skip when data flow not needed)
128
+ if not self.config.performance.skip_data_flow:
129
+ self._perform_deep_analysis(tree, module_name, file_path, result)
129
130
 
130
131
  self.stats['files_processed'] += 1
131
132
  return result
@@ -164,12 +165,18 @@ class FileAnalyzer:
164
165
  result['mutations'] = dfg_res.mutations
165
166
  result['data_flows'] = dfg_res.data_flows
166
167
 
167
- # Update function calls from CG extractor which is more robust
168
+ # Update function calls from CG extractor which is more robust.
169
+ # Use set-based merge to avoid duplicate call entries (ast.walk
170
+ # in _process_function already extracts calls).
168
171
  cg_ext = CallGraphExtractor(self.config)
169
172
  cg_res = cg_ext.extract(tree, module_name, file_path)
170
173
  for func_name, cg_func in cg_res.functions.items():
171
174
  if func_name in result['functions']:
172
- result['functions'][func_name].calls.extend(list(cg_func.calls))
175
+ existing = set(result['functions'][func_name].calls)
176
+ for c in cg_func.calls:
177
+ if c not in existing:
178
+ result['functions'][func_name].calls.append(c)
179
+ existing.add(c)
173
180
  except Exception as e:
174
181
  if self.config.verbose:
175
182
  print(f"Error in deep analysis for {file_path}: {e}")
@@ -282,6 +282,52 @@ class PersistentCache:
282
282
  except OSError:
283
283
  return 0.0
284
284
 
285
+ def _cleanup_stale_exports(self, cutoff: float) -> int:
286
+ """Remove export directories older than *cutoff*.
287
+
288
+ Returns the number of removed export directories.
289
+ """
290
+ removed = 0
291
+ if not self._exports_dir.exists():
292
+ return removed
293
+ for export_dir in list(self._exports_dir.iterdir()):
294
+ if not export_dir.is_dir():
295
+ continue
296
+ complete = export_dir / "_complete"
297
+ try:
298
+ if complete.exists():
299
+ ts = float(complete.read_text())
300
+ else:
301
+ ts = export_dir.stat().st_mtime
302
+ if ts < cutoff:
303
+ shutil.rmtree(export_dir, ignore_errors=True)
304
+ removed += 1
305
+ except (ValueError, OSError):
306
+ pass
307
+ return removed
308
+
309
+ def _cleanup_orphaned_files(self, cutoff: float, known: set) -> int:
310
+ """Remove orphaned file-level cache entries older than *cutoff*.
311
+
312
+ *known* is a set of hash stems still referenced by the manifest.
313
+ Returns the number of removed files.
314
+ """
315
+ removed = 0
316
+ if not self._files_dir.exists():
317
+ return removed
318
+ for f in list(self._files_dir.iterdir()):
319
+ if not f.is_file():
320
+ continue
321
+ if f.stem in known:
322
+ continue # still referenced
323
+ try:
324
+ if f.stat().st_mtime < cutoff:
325
+ f.unlink()
326
+ removed += 1
327
+ except OSError:
328
+ pass
329
+ return removed
330
+
285
331
  def auto_cleanup(self, ttl_days: float = _DEFAULT_TTL_DAYS) -> Dict[str, int]:
286
332
  """Remove stale cache artefacts older than *ttl_days*.
287
333
 
@@ -302,39 +348,11 @@ class PersistentCache:
302
348
  Returns a dict summary `{"exports": n, "files": n}` for logging.
303
349
  """
304
350
  cutoff = time.time() - (ttl_days * 86400)
305
- removed = {"exports": 0, "files": 0}
306
-
307
- # 1) Stale exports (complete or abandoned)
308
- if self._exports_dir.exists():
309
- for export_dir in list(self._exports_dir.iterdir()):
310
- if not export_dir.is_dir():
311
- continue
312
- complete = export_dir / "_complete"
313
- try:
314
- if complete.exists():
315
- ts = float(complete.read_text())
316
- else:
317
- ts = export_dir.stat().st_mtime
318
- if ts < cutoff:
319
- shutil.rmtree(export_dir, ignore_errors=True)
320
- removed["exports"] += 1
321
- except (ValueError, OSError):
322
- pass
323
-
324
- # 2) Orphaned file-level entries older than TTL
325
351
  known = {v.get("hash") for v in self._manifest.get("files", {}).values()}
326
- if self._files_dir.exists():
327
- for f in list(self._files_dir.iterdir()):
328
- if not f.is_file():
329
- continue
330
- if f.stem in known:
331
- continue # still referenced
332
- try:
333
- if f.stat().st_mtime < cutoff:
334
- f.unlink()
335
- removed["files"] += 1
336
- except OSError:
337
- pass
352
+ removed = {
353
+ "exports": self._cleanup_stale_exports(cutoff),
354
+ "files": self._cleanup_orphaned_files(cutoff, known),
355
+ }
338
356
 
339
357
  if removed["exports"] or removed["files"]:
340
358
  logger.debug(
@@ -15,11 +15,21 @@ class RefactoringAnalyzer:
15
15
  self.file_filter = file_filter
16
16
 
17
17
  def perform_refactoring_analysis(self, result: AnalysisResult) -> None:
18
- """Perform deep analysis and detect code smells."""
18
+ """Perform deep analysis and detect code smells.
19
+
20
+ Expensive operations (centrality, cycles, communities, vulture)
21
+ are skipped when the corresponding config flags are set. The
22
+ ``fast_mode`` shortcut disables all of them at once via
23
+ ``PerformanceConfig.apply_fast_mode()``.
24
+ """
25
+ perf = self.config.performance
26
+ if perf.skip_refactoring_analysis:
27
+ return
28
+
19
29
  if self.config.verbose:
20
30
  print("Performing refactoring analysis...")
21
31
 
22
- # 1. Calculate metrics (fan-in/fan-out)
32
+ # 1. Calculate metrics (fan-in/fan-out) — always needed for TOON
23
33
  from ..analysis.call_graph import CallGraphExtractor
24
34
  cg_ext = CallGraphExtractor(self.config)
25
35
  cg_ext.result = result
@@ -29,13 +39,16 @@ class RefactoringAnalyzer:
29
39
  G = self._build_call_graph(result)
30
40
 
31
41
  # 3. Calculate Betweenness Centrality (Bottlenecks)
32
- self._calculate_centrality(G, result)
42
+ if not perf.skip_centrality:
43
+ self._calculate_centrality(G, result)
33
44
 
34
45
  # 4. Detect Circular Dependencies
35
- self._detect_cycles(G, result)
46
+ if not perf.skip_centrality:
47
+ self._detect_cycles(G, result)
36
48
 
37
49
  # 5. Community Detection (Module groups)
38
- self._detect_communities(G, result)
50
+ if not perf.skip_community_detection:
51
+ self._detect_communities(G, result)
39
52
 
40
53
  # 6. Analyze coupling
41
54
  self._analyze_coupling(result)
@@ -43,8 +56,9 @@ class RefactoringAnalyzer:
43
56
  # 7. Detect code smells
44
57
  self._detect_smells(result)
45
58
 
46
- # 8. Dead code detection with vulture
47
- self._detect_dead_code(result)
59
+ # 8. Dead code detection with vulture (slowest step — rescans all files)
60
+ if not perf.skip_dead_code_detection:
61
+ self._detect_dead_code(result)
48
62
 
49
63
  if self.config.verbose:
50
64
  print(f" Detected {len(result.smells)} code smells")
@@ -4,4 +4,4 @@ from .strategies import ScanStrategy, STRATEGY_QUICK, STRATEGY_STANDARD, STRATEG
4
4
  from .cache import StreamingFileCache
5
5
  from .prioritizer import SmartPrioritizer, FilePriority
6
6
  from .scanner import StreamingScanner
7
- from .incremental import IncrementalAnalyzer
7
+ from .incremental import StreamingIncrementalAnalyzer
@@ -9,15 +9,15 @@ from typing import Dict, List, Optional, Tuple
9
9
  from code2llm.core.config import Config, FAST_CONFIG
10
10
 
11
11
 
12
- class IncrementalAnalyzer:
13
- """Incremental analysis with change detection."""
14
-
12
+ class StreamingIncrementalAnalyzer:
13
+ """Incremental analysis with change detection for streaming analyzer."""
14
+
15
15
  def __init__(self, config: Optional[Config] = None):
16
16
  self.config = config or FAST_CONFIG
17
17
  self.state_file = Path(".code2llm_state.json")
18
18
  self.previous_state: Dict[str, str] = {}
19
19
  self._load_state()
20
-
20
+
21
21
  def _load_state(self) -> None:
22
22
  """Load previous analysis state."""
23
23
  if self.state_file.exists():
@@ -27,7 +27,7 @@ class IncrementalAnalyzer:
27
27
  self.previous_state = data.get('file_hashes', {})
28
28
  except Exception:
29
29
  pass
30
-
30
+
31
31
  def _save_state(self, current_state: Dict[str, str]) -> None:
32
32
  """Save current analysis state."""
33
33
  with open(self.state_file, 'w') as f:
@@ -35,7 +35,7 @@ class IncrementalAnalyzer:
35
35
  'file_hashes': current_state,
36
36
  'timestamp': time.time()
37
37
  }, f)
38
-
38
+
39
39
  def get_changed_files(
40
40
  self,
41
41
  project_path: Path
@@ -44,15 +44,15 @@ class IncrementalAnalyzer:
44
44
  changed = []
45
45
  unchanged = []
46
46
  current_state = {}
47
-
47
+
48
48
  for py_file in project_path.rglob("*.py"):
49
49
  try:
50
50
  content = py_file.read_bytes()
51
51
  file_hash = hashlib.md5(content).hexdigest()
52
52
  file_str = str(py_file)
53
-
53
+
54
54
  current_state[file_str] = file_hash
55
-
55
+
56
56
  if file_str in self.previous_state:
57
57
  if self.previous_state[file_str] == file_hash:
58
58
  unchanged.append((file_str, self._get_module_name(py_file, project_path)))
@@ -62,10 +62,10 @@ class IncrementalAnalyzer:
62
62
  changed.append((file_str, self._get_module_name(py_file, project_path)))
63
63
  except Exception:
64
64
  pass
65
-
65
+
66
66
  self._save_state(current_state)
67
67
  return changed, unchanged
68
-
68
+
69
69
  def _get_module_name(self, py_file: Path, project_path: Path) -> str:
70
70
  """Calculate module name."""
71
71
  rel_path = py_file.relative_to(project_path)
@@ -15,7 +15,7 @@ from typing import Dict, Iterator, List, Optional, Tuple
15
15
  from .config import Config, FAST_CONFIG
16
16
  from .streaming import (
17
17
  ScanStrategy, STRATEGY_STANDARD, StreamingFileCache,
18
- SmartPrioritizer, FilePriority, StreamingScanner, IncrementalAnalyzer
18
+ SmartPrioritizer, FilePriority, StreamingScanner, StreamingIncrementalAnalyzer
19
19
  )
20
20
 
21
21
 
@@ -177,5 +177,5 @@ class StreamingAnalyzer:
177
177
  # Re-export for backward compatibility
178
178
  from .streaming import (
179
179
  ScanStrategy, STRATEGY_QUICK, STRATEGY_STANDARD, STRATEGY_DEEP,
180
- StreamingFileCache, SmartPrioritizer, FilePriority, IncrementalAnalyzer
180
+ StreamingFileCache, SmartPrioritizer, FilePriority, StreamingIncrementalAnalyzer
181
181
  )