code2llm 0.5.108__tar.gz → 0.5.109__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.108 → code2llm-0.5.109}/PKG-INFO +3 -2
- {code2llm-0.5.108 → code2llm-0.5.109}/README.md +1 -1
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/__init__.py +1 -1
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli_commands.py +66 -36
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/yaml_exporter.py +30 -14
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/nlp/__init__.py +1 -1
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm.egg-info/PKG-INFO +3 -2
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm.egg-info/requires.txt +1 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/pyproject.toml +6 -1
- {code2llm-0.5.108 → code2llm-0.5.109}/setup.py +1 -1
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_edge_cases.py +6 -5
- {code2llm-0.5.108 → code2llm-0.5.109}/LICENSE +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/__main__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/call_graph.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/cfg.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/coupling.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/data_analysis.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/dfg.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/pipeline_detector.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/side_effects.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/smells.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/type_inference.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/utils/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/analysis/utils/ast_helpers.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/api.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli_analysis.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli_exports/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli_exports/code2logic.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli_exports/formats.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli_exports/orchestrator.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli_exports/prompt.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/cli_parser.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/analyzer.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/ast_registry.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/config.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/export_pipeline.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/file_analyzer.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/file_cache.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/file_filter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/gitignore.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/incremental.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/base.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/cpp.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/csharp.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/generic.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/go_lang.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/java.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/php.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/ruby.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/rust.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/ts_extractors.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/ts_parser.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/lang/typescript.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/large_repo.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/models.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/refactoring.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/repo_files.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/streaming/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/streaming/cache.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/streaming/incremental.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/streaming/prioritizer.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/streaming/scanner.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/streaming/strategies.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/streaming_analyzer.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/core/toon_size_manager.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/article_view.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/base.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/context_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/context_view.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/evolution_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/flow_constants.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/flow_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/flow_renderer.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/html_dashboard.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/index_generator.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/json_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/llm_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/map_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/mermaid_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/project_yaml_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/readme_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/report_generators.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/toon/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/toon/helpers.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/toon/metrics.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/toon/module_detail.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/toon/renderer.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/toon.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/toon_view.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/exporters/validate_project.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/generators/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/generators/llm_flow.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/generators/llm_task.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/generators/mermaid.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/nlp/config.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/nlp/entity_resolution.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/nlp/intent_matching.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/nlp/normalization.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/nlp/pipeline.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/patterns/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/patterns/detector.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/refactor/__init__.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm/refactor/prompt_engine.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm.egg-info/SOURCES.txt +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm.egg-info/dependency_links.txt +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm.egg-info/entry_points.txt +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/code2llm.egg-info/top_level.txt +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/setup.cfg +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_advanced_analysis.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_analyzer.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_deep_analysis.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_flow_exporter.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_format_quality.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_multilanguage_e2e.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_nlp_pipeline.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_nonpython_cc_calls.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_pipeline_detector.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_project_toon_export.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_prompt_engine.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_prompt_txt.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/tests/test_refactoring_engine.py +0 -0
- {code2llm-0.5.108 → code2llm-0.5.109}/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.109
|
|
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
|
|
@@ -50,6 +50,7 @@ Requires-Dist: tree-sitter-ruby>=0.21
|
|
|
50
50
|
Provides-Extra: dev
|
|
51
51
|
Requires-Dist: pytest>=6.2; extra == "dev"
|
|
52
52
|
Requires-Dist: pytest-cov>=2.12; extra == "dev"
|
|
53
|
+
Requires-Dist: pytest-xdist>=3.0; extra == "dev"
|
|
53
54
|
Requires-Dist: black>=21.0; extra == "dev"
|
|
54
55
|
Requires-Dist: flake8>=3.9; extra == "dev"
|
|
55
56
|
Requires-Dist: mypy>=0.910; extra == "dev"
|
|
@@ -66,7 +67,7 @@ Dynamic: requires-python
|
|
|
66
67
|
|
|
67
68
|
## AI Cost Tracking
|
|
68
69
|
|
|
69
|
-
    
|
|
70
71
|
  
|
|
71
72
|
|
|
72
73
|
- 🤖 **LLM usage:** $7.5000 (154 commits)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
## AI Cost Tracking
|
|
5
5
|
|
|
6
|
-
    
|
|
7
7
|
  
|
|
8
8
|
|
|
9
9
|
- 🤖 **LLM usage:** $7.5000 (154 commits)
|
|
@@ -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.109"
|
|
12
12
|
__author__ = "STTS Project"
|
|
13
13
|
|
|
14
14
|
# Core analysis components (lightweight, always needed)
|
|
@@ -109,71 +109,101 @@ def print_start_info(args, source_path: Path, output_dir: Path) -> None:
|
|
|
109
109
|
|
|
110
110
|
def validate_chunked_output(output_dir: Path, args) -> bool:
|
|
111
111
|
"""Validate generated chunked output.
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
Checks:
|
|
114
114
|
1. All chunks have required files (analysis.toon, context.md, evolution.toon.yaml)
|
|
115
115
|
2. Files are not empty
|
|
116
116
|
3. Report summary
|
|
117
|
-
|
|
117
|
+
|
|
118
118
|
Returns True if valid, False otherwise.
|
|
119
119
|
"""
|
|
120
120
|
if not output_dir.exists():
|
|
121
121
|
print(f"✗ Output directory does not exist: {output_dir}", file=sys.stderr)
|
|
122
122
|
return False
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
chunk_dirs = [d for d in output_dir.iterdir() if d.is_dir()]
|
|
126
|
-
|
|
123
|
+
|
|
124
|
+
chunk_dirs = _get_chunk_dirs(output_dir)
|
|
127
125
|
if not chunk_dirs:
|
|
128
126
|
print(f"✗ No chunk directories found in: {output_dir}", file=sys.stderr)
|
|
129
127
|
return False
|
|
130
|
-
|
|
128
|
+
|
|
131
129
|
required_files = ['analysis.toon.yaml', 'context.md', 'evolution.toon.yaml']
|
|
130
|
+
issues, valid_chunks = _validate_chunks(chunk_dirs, required_files)
|
|
131
|
+
|
|
132
|
+
_print_validation_summary(chunk_dirs, valid_chunks, issues)
|
|
133
|
+
return len(issues) == 0
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _get_chunk_dirs(output_dir: Path) -> list[Path]:
|
|
137
|
+
"""Find all chunk directories in output directory."""
|
|
138
|
+
return [d for d in output_dir.iterdir() if d.is_dir()]
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _validate_chunks(chunk_dirs: list[Path], required_files: list[str]) -> tuple:
|
|
142
|
+
"""Validate all chunks and return issues and valid chunks."""
|
|
132
143
|
issues = []
|
|
133
144
|
valid_chunks = []
|
|
134
|
-
|
|
135
|
-
print(f"\n🔍 Validating {len(chunk_dirs)} chunks
|
|
145
|
+
|
|
146
|
+
print(f"\n🔍 Validating {len(chunk_dirs)} chunks")
|
|
136
147
|
print("-" * 50)
|
|
137
|
-
|
|
148
|
+
|
|
138
149
|
for chunk_dir in sorted(chunk_dirs):
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
for req_file in required_files:
|
|
143
|
-
file_path = chunk_dir / req_file
|
|
144
|
-
if not file_path.exists():
|
|
145
|
-
chunk_issues.append(f" missing {req_file}")
|
|
146
|
-
elif file_path.stat().st_size == 0:
|
|
147
|
-
chunk_issues.append(f" empty {req_file}")
|
|
148
|
-
|
|
150
|
+
chunk_issues = _validate_single_chunk(chunk_dir, required_files)
|
|
151
|
+
|
|
149
152
|
if chunk_issues:
|
|
150
|
-
issues.append((
|
|
151
|
-
|
|
152
|
-
for issue in chunk_issues:
|
|
153
|
-
print(f" {issue}")
|
|
153
|
+
issues.append((chunk_dir.name, chunk_issues))
|
|
154
|
+
_print_chunk_errors(chunk_dir.name, chunk_issues)
|
|
154
155
|
else:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
sizes.append(f"{req_file}:{size//1024}KB" if size > 1024 else f"{req_file}:{size}B")
|
|
160
|
-
valid_chunks.append(chunk_name)
|
|
161
|
-
print(f"✓ {chunk_name} ({', '.join(sizes)})")
|
|
162
|
-
|
|
156
|
+
sizes = _get_file_sizes(chunk_dir, required_files)
|
|
157
|
+
valid_chunks.append(chunk_dir.name)
|
|
158
|
+
print(f"✓ {chunk_dir.name} ({sizes})")
|
|
159
|
+
|
|
163
160
|
print("-" * 50)
|
|
161
|
+
return issues, valid_chunks
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _validate_single_chunk(chunk_dir: Path, required_files: list[str]) -> list[str]:
|
|
165
|
+
"""Validate a single chunk directory. Returns list of issues."""
|
|
166
|
+
chunk_issues = []
|
|
167
|
+
|
|
168
|
+
for req_file in required_files:
|
|
169
|
+
file_path = chunk_dir / req_file
|
|
170
|
+
if not file_path.exists():
|
|
171
|
+
chunk_issues.append(f" missing {req_file}")
|
|
172
|
+
elif file_path.stat().st_size == 0:
|
|
173
|
+
chunk_issues.append(f" empty {req_file}")
|
|
174
|
+
|
|
175
|
+
return chunk_issues
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _get_file_sizes(chunk_dir: Path, required_files: list[str]) -> str:
|
|
179
|
+
"""Get formatted file sizes for a chunk."""
|
|
180
|
+
sizes = []
|
|
181
|
+
for req_file in required_files:
|
|
182
|
+
size = (chunk_dir / req_file).stat().st_size
|
|
183
|
+
sizes.append(f"{req_file}:{size//1024}KB" if size > 1024 else f"{req_file}:{size}B")
|
|
184
|
+
return ", ".join(sizes)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _print_chunk_errors(chunk_name: str, chunk_issues: list[str]) -> None:
|
|
188
|
+
"""Print errors for a chunk."""
|
|
189
|
+
print(f"✗ {chunk_name}")
|
|
190
|
+
for issue in chunk_issues:
|
|
191
|
+
print(f" {issue}")
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _print_validation_summary(chunk_dirs: list, valid_chunks: list, issues: list) -> None:
|
|
195
|
+
"""Print validation summary report."""
|
|
164
196
|
print(f"\n📊 Validation Summary:")
|
|
165
197
|
print(f" Total chunks: {len(chunk_dirs)}")
|
|
166
198
|
print(f" Valid: {len(valid_chunks)}")
|
|
167
199
|
print(f" Issues: {len(issues)}")
|
|
168
|
-
|
|
200
|
+
|
|
169
201
|
if issues:
|
|
170
202
|
print(f"\n⚠️ {len(issues)} chunk(s) have issues:")
|
|
171
|
-
for chunk_name,
|
|
203
|
+
for chunk_name, _ in issues:
|
|
172
204
|
print(f" - {chunk_name}")
|
|
173
|
-
return False
|
|
174
205
|
else:
|
|
175
206
|
print(f"\n✅ All {len(valid_chunks)} chunks are valid!")
|
|
176
|
-
return True
|
|
177
207
|
|
|
178
208
|
|
|
179
209
|
def generate_llm_context(args_list):
|
|
@@ -132,24 +132,40 @@ class YAMLExporter(Exporter):
|
|
|
132
132
|
connected: Set[str] = set()
|
|
133
133
|
edges: List[Dict] = []
|
|
134
134
|
seen_pairs: Set[Tuple[str, str]] = set()
|
|
135
|
-
|
|
135
|
+
|
|
136
136
|
for func_name, fi in result.functions.items():
|
|
137
|
-
for callee in fi.calls[:max_calls]:
|
|
138
|
-
resolved = self._resolve_callee(callee, result.functions)
|
|
139
|
-
if resolved and resolved != func_name:
|
|
140
|
-
connected.add(func_name)
|
|
141
|
-
connected.add(resolved)
|
|
142
|
-
pair = (func_name, resolved)
|
|
143
|
-
if pair not in seen_pairs:
|
|
144
|
-
seen_pairs.add(pair)
|
|
145
|
-
edges.append(self._create_edge(func_name, resolved, callee))
|
|
146
|
-
if len(edges) >= max_edges:
|
|
147
|
-
return connected, edges
|
|
148
137
|
if len(edges) >= max_edges:
|
|
149
|
-
|
|
150
|
-
|
|
138
|
+
break
|
|
139
|
+
self._process_function_calls(
|
|
140
|
+
func_name, fi, result.functions, max_calls, max_edges,
|
|
141
|
+
connected, edges, seen_pairs
|
|
142
|
+
)
|
|
143
|
+
|
|
151
144
|
return connected, edges
|
|
152
145
|
|
|
146
|
+
def _process_function_calls(
|
|
147
|
+
self, func_name: str, fi: FunctionInfo, functions: Dict[str, FunctionInfo],
|
|
148
|
+
max_calls: int, max_edges: int, connected: Set[str], edges: List[Dict],
|
|
149
|
+
seen_pairs: Set[Tuple[str, str]]
|
|
150
|
+
) -> None:
|
|
151
|
+
"""Process calls for a single function."""
|
|
152
|
+
for callee in fi.calls[:max_calls]:
|
|
153
|
+
if len(edges) >= max_edges:
|
|
154
|
+
break
|
|
155
|
+
resolved = self._resolve_callee(callee, functions)
|
|
156
|
+
if self._should_add_edge(func_name, resolved, seen_pairs):
|
|
157
|
+
connected.add(func_name)
|
|
158
|
+
connected.add(resolved)
|
|
159
|
+
seen_pairs.add((func_name, resolved))
|
|
160
|
+
edges.append(self._create_edge(func_name, resolved, callee))
|
|
161
|
+
|
|
162
|
+
@staticmethod
|
|
163
|
+
def _should_add_edge(func_name: str, resolved: Optional[str], seen_pairs: Set[Tuple[str, str]]) -> bool:
|
|
164
|
+
"""Check if edge should be added (valid callee and not duplicate)."""
|
|
165
|
+
if not resolved or resolved == func_name:
|
|
166
|
+
return False
|
|
167
|
+
return (func_name, resolved) not in seen_pairs
|
|
168
|
+
|
|
153
169
|
@staticmethod
|
|
154
170
|
def _create_edge(caller: str, resolved: str, callee: str) -> Dict:
|
|
155
171
|
"""Create edge dict with call type classification."""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.109
|
|
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
|
|
@@ -50,6 +50,7 @@ Requires-Dist: tree-sitter-ruby>=0.21
|
|
|
50
50
|
Provides-Extra: dev
|
|
51
51
|
Requires-Dist: pytest>=6.2; extra == "dev"
|
|
52
52
|
Requires-Dist: pytest-cov>=2.12; extra == "dev"
|
|
53
|
+
Requires-Dist: pytest-xdist>=3.0; extra == "dev"
|
|
53
54
|
Requires-Dist: black>=21.0; extra == "dev"
|
|
54
55
|
Requires-Dist: flake8>=3.9; extra == "dev"
|
|
55
56
|
Requires-Dist: mypy>=0.910; extra == "dev"
|
|
@@ -66,7 +67,7 @@ Dynamic: requires-python
|
|
|
66
67
|
|
|
67
68
|
## AI Cost Tracking
|
|
68
69
|
|
|
69
|
-
    
|
|
70
71
|
  
|
|
71
72
|
|
|
72
73
|
- 🤖 **LLM usage:** $7.5000 (154 commits)
|
|
@@ -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.109"
|
|
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.8"
|
|
@@ -67,6 +67,7 @@ dependencies = [
|
|
|
67
67
|
dev = [
|
|
68
68
|
"pytest>=6.2",
|
|
69
69
|
"pytest-cov>=2.12",
|
|
70
|
+
"pytest-xdist>=3.0",
|
|
70
71
|
"black>=21.0",
|
|
71
72
|
"flake8>=3.9",
|
|
72
73
|
"mypy>=0.910",
|
|
@@ -94,6 +95,10 @@ ignore_missing_imports = true
|
|
|
94
95
|
[tool.pytest.ini_options]
|
|
95
96
|
testpaths = ["tests"]
|
|
96
97
|
python_files = "test_*.py"
|
|
98
|
+
addopts = "-n auto" # Run tests in parallel using pytest-xdist
|
|
99
|
+
markers = [
|
|
100
|
+
"slow: marks tests as slow (deselect with '-m \"not slow\"')"
|
|
101
|
+
]
|
|
97
102
|
|
|
98
103
|
[tool.pfix]
|
|
99
104
|
# Self-healing Python configuration
|
|
@@ -50,22 +50,23 @@ class TestEdgeCases:
|
|
|
50
50
|
finally:
|
|
51
51
|
shutil.rmtree(tmp_dir)
|
|
52
52
|
|
|
53
|
+
@pytest.mark.slow
|
|
53
54
|
def test_very_large_file(self):
|
|
54
55
|
"""Handle very large Python file."""
|
|
55
56
|
tmp_dir = Path(tempfile.mkdtemp())
|
|
56
57
|
try:
|
|
57
|
-
# Create large file (1000
|
|
58
|
-
lines = [f"def func_{i}(): pass" for i in range(
|
|
58
|
+
# Create large file (200 functions - reduced from 1000 for faster tests)
|
|
59
|
+
lines = [f"def func_{i}(): pass" for i in range(200)]
|
|
59
60
|
(tmp_dir / "large.py").write_text('\n'.join(lines))
|
|
60
|
-
|
|
61
|
+
|
|
61
62
|
config = Config(
|
|
62
63
|
mode="static",
|
|
63
64
|
filters=FilterConfig(exclude_patterns=[], min_function_lines=1)
|
|
64
65
|
)
|
|
65
66
|
analyzer = ProjectAnalyzer(config)
|
|
66
67
|
result = analyzer.analyze_project(str(tmp_dir))
|
|
67
|
-
|
|
68
|
-
assert result.get_function_count() >=
|
|
68
|
+
|
|
69
|
+
assert result.get_function_count() >= 200
|
|
69
70
|
finally:
|
|
70
71
|
shutil.rmtree(tmp_dir)
|
|
71
72
|
|
|
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
|