code2logic 1.0.45__tar.gz → 1.0.47__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.
- {code2logic-1.0.45 → code2logic-1.0.47}/PKG-INFO +1 -1
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/__init__.py +1 -1
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/analyzer.py +177 -45
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/cli.py +7 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/pyproject.toml +1 -1
- {code2logic-1.0.45 → code2logic-1.0.47}/LICENSE +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/README.md +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/__main__.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/adaptive.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/base.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/base_generator.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/benchmark.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/benchmarks/__init__.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/benchmarks/common.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/benchmarks/results.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/benchmarks/runner.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/chunked_reproduction.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/code_review.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/config.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/core/__init__.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/dependency.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/errors.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/file_formats.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/formats/__init__.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/function_logic.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/generators.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/gherkin.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/integrations/__init__.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/intent.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/llm/__init__.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/llm.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/llm_clients.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/llm_profiler.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/logicml.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/markdown_format.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/mcp_server.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/metrics.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/models.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/parsers.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/project_comparison.md +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/project_reproducer.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/prompts.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/py.typed +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/quality.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/refactor.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/reproducer.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/reproduction.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/schemas/__init__.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/schemas/json_schema.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/schemas/logicml_schema.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/schemas/markdown_schema.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/schemas/yaml_schema.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/shared_utils.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/similarity.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/terminal.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/tools/__init__.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/toon_format.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/universal.py +0 -0
- {code2logic-1.0.45 → code2logic-1.0.47}/code2logic/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2logic
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.47
|
|
4
4
|
Summary: Code2Logic - Source code to logical representation converter for LLM analysis, featuring Tree-sitter parsing, dependency graph analysis, and multi-language support.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -5,6 +5,8 @@ Provides the high-level API for analyzing codebases.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import logging
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
8
10
|
import sys
|
|
9
11
|
import time
|
|
10
12
|
from collections import defaultdict
|
|
@@ -108,6 +110,7 @@ class ProjectAnalyzer:
|
|
|
108
110
|
verbose: bool = False,
|
|
109
111
|
include_private: bool = False,
|
|
110
112
|
enable_similarity: bool = True,
|
|
113
|
+
respect_gitignore: bool = True,
|
|
111
114
|
):
|
|
112
115
|
"""
|
|
113
116
|
Initialize the project analyzer.
|
|
@@ -123,6 +126,7 @@ class ProjectAnalyzer:
|
|
|
123
126
|
self.verbose = verbose
|
|
124
127
|
self.include_private = include_private
|
|
125
128
|
self.enable_similarity = enable_similarity
|
|
129
|
+
self.respect_gitignore = respect_gitignore
|
|
126
130
|
self.modules: List[ModuleInfo] = []
|
|
127
131
|
self.languages: Dict[str, int] = defaultdict(int)
|
|
128
132
|
|
|
@@ -218,63 +222,191 @@ class ProjectAnalyzer:
|
|
|
218
222
|
|
|
219
223
|
def _scan_files(self):
|
|
220
224
|
"""Scan and parse all source files."""
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
225
|
+
scan_start = time.time()
|
|
226
|
+
files_seen = 0
|
|
227
|
+
files_parsed = 0
|
|
228
|
+
files_matched = 0
|
|
229
|
+
scan_progress_every = 500
|
|
230
|
+
|
|
231
|
+
git_file_list: Optional[List[Path]] = None
|
|
232
|
+
if self.respect_gitignore:
|
|
233
|
+
git_file_list = self._get_git_nonignored_files()
|
|
234
|
+
if git_file_list is not None and self.verbose:
|
|
235
|
+
log.info("Using git file list (non-ignored): files=%d", len(git_file_list))
|
|
236
|
+
|
|
237
|
+
if git_file_list is not None:
|
|
238
|
+
for fp in git_file_list:
|
|
239
|
+
files_seen += 1
|
|
240
|
+
filename = fp.name
|
|
241
|
+
|
|
242
|
+
if filename in self.IGNORE_FILES:
|
|
243
|
+
continue
|
|
224
244
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
245
|
+
ext = fp.suffix.lower()
|
|
246
|
+
language = self.LANGUAGE_EXTENSIONS.get(ext)
|
|
247
|
+
if language is None and ext == '':
|
|
248
|
+
try:
|
|
249
|
+
with fp.open('r', encoding='utf-8', errors='ignore') as f:
|
|
250
|
+
language = self._language_from_shebang(f.readline())
|
|
251
|
+
except Exception:
|
|
252
|
+
language = None
|
|
228
253
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
254
|
+
if language is None:
|
|
255
|
+
continue
|
|
256
|
+
|
|
257
|
+
files_matched += 1
|
|
258
|
+
self.languages[language] += 1
|
|
259
|
+
|
|
260
|
+
if self.verbose and files_seen > 0 and (files_seen % scan_progress_every) == 0:
|
|
261
|
+
log.info(
|
|
262
|
+
"Scan progress: seen=%d matched=%d parsed=%d modules=%d time=%.2fs",
|
|
263
|
+
files_seen,
|
|
264
|
+
files_matched,
|
|
265
|
+
files_parsed,
|
|
266
|
+
len(self.modules),
|
|
267
|
+
time.time() - scan_start,
|
|
268
|
+
)
|
|
232
269
|
|
|
233
|
-
ext = fp.suffix.lower()
|
|
234
|
-
language = self.LANGUAGE_EXTENSIONS.get(ext)
|
|
235
|
-
if language is None and ext == '':
|
|
236
270
|
try:
|
|
237
|
-
|
|
238
|
-
language = self._language_from_shebang(f.readline())
|
|
271
|
+
content = fp.read_text(encoding='utf-8', errors='ignore')
|
|
239
272
|
except Exception:
|
|
240
|
-
|
|
273
|
+
continue
|
|
241
274
|
|
|
242
|
-
|
|
243
|
-
|
|
275
|
+
try:
|
|
276
|
+
rel_path = str(fp.relative_to(self.root_path))
|
|
277
|
+
except Exception:
|
|
278
|
+
rel_path = str(fp)
|
|
244
279
|
|
|
245
|
-
|
|
280
|
+
module = None
|
|
281
|
+
try:
|
|
282
|
+
if self.ts_parser and self.ts_parser.is_available(language):
|
|
283
|
+
module = self.ts_parser.parse(rel_path, content, language)
|
|
284
|
+
except Exception as e:
|
|
285
|
+
if self.verbose:
|
|
286
|
+
log.debug("Tree-sitter parser failed for %s: %s", rel_path, e)
|
|
287
|
+
|
|
288
|
+
if module is None:
|
|
289
|
+
try:
|
|
290
|
+
module = self.fallback_parser.parse(rel_path, content, language)
|
|
291
|
+
except Exception as e:
|
|
292
|
+
if self.verbose:
|
|
293
|
+
log.debug("Fallback parser failed for %s: %s", rel_path, e)
|
|
294
|
+
continue
|
|
295
|
+
|
|
296
|
+
if module:
|
|
297
|
+
files_parsed += 1
|
|
298
|
+
try:
|
|
299
|
+
module.file_bytes = fp.stat().st_size
|
|
300
|
+
except Exception:
|
|
301
|
+
module.file_bytes = len(content.encode('utf-8', errors='ignore'))
|
|
302
|
+
self.modules.append(module)
|
|
246
303
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
304
|
+
else:
|
|
305
|
+
for root, dirnames, filenames in os.walk(self.root_path):
|
|
306
|
+
dirnames[:] = [d for d in dirnames if d not in self.IGNORE_DIRS]
|
|
307
|
+
for filename in filenames:
|
|
308
|
+
files_seen += 1
|
|
309
|
+
fp = Path(root) / filename
|
|
310
|
+
|
|
311
|
+
if filename in self.IGNORE_FILES:
|
|
312
|
+
continue
|
|
313
|
+
|
|
314
|
+
ext = fp.suffix.lower()
|
|
315
|
+
language = self.LANGUAGE_EXTENSIONS.get(ext)
|
|
316
|
+
if language is None and ext == '':
|
|
317
|
+
try:
|
|
318
|
+
with fp.open('r', encoding='utf-8', errors='ignore') as f:
|
|
319
|
+
language = self._language_from_shebang(f.readline())
|
|
320
|
+
except Exception:
|
|
321
|
+
language = None
|
|
322
|
+
|
|
323
|
+
if language is None:
|
|
324
|
+
continue
|
|
325
|
+
|
|
326
|
+
files_matched += 1
|
|
327
|
+
self.languages[language] += 1
|
|
328
|
+
|
|
329
|
+
if self.verbose and files_seen > 0 and (files_seen % scan_progress_every) == 0:
|
|
330
|
+
log.info(
|
|
331
|
+
"Scan progress: seen=%d matched=%d parsed=%d modules=%d time=%.2fs",
|
|
332
|
+
files_seen,
|
|
333
|
+
files_matched,
|
|
334
|
+
files_parsed,
|
|
335
|
+
len(self.modules),
|
|
336
|
+
time.time() - scan_start,
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
try:
|
|
340
|
+
content = fp.read_text(encoding='utf-8', errors='ignore')
|
|
341
|
+
except Exception:
|
|
342
|
+
continue
|
|
343
|
+
|
|
344
|
+
try:
|
|
345
|
+
rel_path = str(fp.relative_to(self.root_path))
|
|
346
|
+
except Exception:
|
|
347
|
+
rel_path = str(fp)
|
|
348
|
+
|
|
349
|
+
module = None
|
|
350
|
+
try:
|
|
351
|
+
if self.ts_parser and self.ts_parser.is_available(language):
|
|
352
|
+
module = self.ts_parser.parse(rel_path, content, language)
|
|
353
|
+
except Exception as e:
|
|
354
|
+
if self.verbose:
|
|
355
|
+
log.debug("Tree-sitter parser failed for %s: %s", rel_path, e)
|
|
356
|
+
|
|
357
|
+
if module is None:
|
|
358
|
+
try:
|
|
359
|
+
module = self.fallback_parser.parse(rel_path, content, language)
|
|
360
|
+
except Exception as e:
|
|
361
|
+
if self.verbose:
|
|
362
|
+
log.debug("Fallback parser failed for %s: %s", rel_path, e)
|
|
363
|
+
continue
|
|
364
|
+
|
|
365
|
+
if module:
|
|
366
|
+
files_parsed += 1
|
|
367
|
+
try:
|
|
368
|
+
module.file_bytes = fp.stat().st_size
|
|
369
|
+
except Exception:
|
|
370
|
+
module.file_bytes = len(content.encode('utf-8', errors='ignore'))
|
|
371
|
+
self.modules.append(module)
|
|
252
372
|
|
|
253
|
-
|
|
373
|
+
if self.verbose:
|
|
374
|
+
log.info(
|
|
375
|
+
"Scan finished: seen=%d matched=%d parsed=%d modules=%d time=%.2fs",
|
|
376
|
+
files_seen,
|
|
377
|
+
files_matched,
|
|
378
|
+
files_parsed,
|
|
379
|
+
len(self.modules),
|
|
380
|
+
time.time() - scan_start,
|
|
381
|
+
)
|
|
254
382
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
except Exception as e:
|
|
261
|
-
if self.verbose:
|
|
262
|
-
log.debug("Tree-sitter parser failed for %s: %s", rel_path, e)
|
|
383
|
+
def _get_git_nonignored_files(self) -> Optional[List[Path]]:
|
|
384
|
+
"""Return list of non-ignored files according to git, or None if unavailable."""
|
|
385
|
+
git_dir = self.root_path / '.git'
|
|
386
|
+
if not git_dir.exists():
|
|
387
|
+
return None
|
|
263
388
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
389
|
+
try:
|
|
390
|
+
proc = subprocess.run(
|
|
391
|
+
['git', '-C', str(self.root_path), 'ls-files', '-co', '--exclude-standard'],
|
|
392
|
+
check=False,
|
|
393
|
+
stdout=subprocess.PIPE,
|
|
394
|
+
stderr=subprocess.DEVNULL,
|
|
395
|
+
text=True,
|
|
396
|
+
)
|
|
397
|
+
except Exception:
|
|
398
|
+
return None
|
|
271
399
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
400
|
+
if proc.returncode != 0:
|
|
401
|
+
return None
|
|
402
|
+
|
|
403
|
+
files: List[Path] = []
|
|
404
|
+
for line in (proc.stdout or '').splitlines():
|
|
405
|
+
rel = (line or '').strip()
|
|
406
|
+
if not rel:
|
|
407
|
+
continue
|
|
408
|
+
files.append(self.root_path / rel)
|
|
409
|
+
return files
|
|
278
410
|
|
|
279
411
|
def _detect_entrypoints(self) -> List[str]:
|
|
280
412
|
"""Detect project entry points."""
|
|
@@ -510,6 +510,7 @@ def _code2logic_llm_cli(argv: list[str]) -> None:
|
|
|
510
510
|
|
|
511
511
|
|
|
512
512
|
def main(argv=None):
|
|
513
|
+
cli_start = time.time()
|
|
513
514
|
parser = argparse.ArgumentParser(
|
|
514
515
|
description='Analyze source code and generate logical representations',
|
|
515
516
|
formatter_class=argparse.RawDescriptionHelpFormatter
|
|
@@ -644,6 +645,11 @@ Detail levels (columns in csv/json/yaml):
|
|
|
644
645
|
action='store_true',
|
|
645
646
|
help='Disable Tree-sitter (use fallback parser)'
|
|
646
647
|
)
|
|
648
|
+
parser.add_argument(
|
|
649
|
+
'--no-gitignore',
|
|
650
|
+
action='store_true',
|
|
651
|
+
help='Do not respect .gitignore (scan all files under path)'
|
|
652
|
+
)
|
|
647
653
|
parser.add_argument(
|
|
648
654
|
'--no-similarity',
|
|
649
655
|
action='store_true',
|
|
@@ -828,6 +834,7 @@ Detail levels (columns in csv/json/yaml):
|
|
|
828
834
|
use_treesitter=not args.no_treesitter,
|
|
829
835
|
verbose=args.verbose or args.debug,
|
|
830
836
|
enable_similarity=not args.no_similarity,
|
|
837
|
+
respect_gitignore=not args.no_gitignore,
|
|
831
838
|
)
|
|
832
839
|
project = analyzer.analyze()
|
|
833
840
|
analyze_time = time.time() - analyze_start
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "code2logic"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.47"
|
|
8
8
|
description = "Code2Logic - Source code to logical representation converter for LLM analysis, featuring Tree-sitter parsing, dependency graph analysis, and multi-language support."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|