sourcecode 0.44.0__py3-none-any.whl → 0.45.0__py3-none-any.whl
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.
- sourcecode/__init__.py +1 -1
- sourcecode/cli.py +71 -24
- sourcecode/contract_pipeline.py +3 -1
- sourcecode/detectors/heuristic.py +9 -1
- sourcecode/env_analyzer.py +2 -2
- sourcecode/serializer.py +9 -3
- {sourcecode-0.44.0.dist-info → sourcecode-0.45.0.dist-info}/METADATA +1 -1
- {sourcecode-0.44.0.dist-info → sourcecode-0.45.0.dist-info}/RECORD +11 -11
- {sourcecode-0.44.0.dist-info → sourcecode-0.45.0.dist-info}/WHEEL +0 -0
- {sourcecode-0.44.0.dist-info → sourcecode-0.45.0.dist-info}/entry_points.txt +0 -0
- {sourcecode-0.44.0.dist-info → sourcecode-0.45.0.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/cli.py
CHANGED
|
@@ -660,6 +660,21 @@ def main(
|
|
|
660
660
|
)
|
|
661
661
|
raise typer.Exit(code=1)
|
|
662
662
|
|
|
663
|
+
if symbol and mode not in ("contract", "standard"):
|
|
664
|
+
typer.echo(
|
|
665
|
+
f"Error: --symbol requires --mode contract or standard (got '{mode}'). "
|
|
666
|
+
"Symbol search uses the contract pipeline which does not run in raw mode.",
|
|
667
|
+
err=True,
|
|
668
|
+
)
|
|
669
|
+
raise typer.Exit(code=1)
|
|
670
|
+
|
|
671
|
+
if entrypoints_only and mode not in ("contract", "standard"):
|
|
672
|
+
typer.echo(
|
|
673
|
+
f"Error: --entrypoints-only requires --mode contract or standard (got '{mode}').",
|
|
674
|
+
err=True,
|
|
675
|
+
)
|
|
676
|
+
raise typer.Exit(code=1)
|
|
677
|
+
|
|
663
678
|
if dependency_depth > 0:
|
|
664
679
|
typer.echo(
|
|
665
680
|
f"[warning] --dependency-depth {dependency_depth} has no effect: "
|
|
@@ -1257,7 +1272,13 @@ def main(
|
|
|
1257
1272
|
eco_order = 0 if d.ecosystem == primary_ecosystem else 1
|
|
1258
1273
|
return (role_order, eco_order, d.name.lower())
|
|
1259
1274
|
|
|
1260
|
-
|
|
1275
|
+
_seen_dep_names: set[str] = set()
|
|
1276
|
+
_deduped_deps: list[Any] = []
|
|
1277
|
+
for d in sorted(direct_deps, key=_dep_sort_key):
|
|
1278
|
+
if d.name not in _seen_dep_names:
|
|
1279
|
+
_seen_dep_names.add(d.name)
|
|
1280
|
+
_deduped_deps.append(d)
|
|
1281
|
+
sm.key_dependencies = _deduped_deps[:15]
|
|
1261
1282
|
|
|
1262
1283
|
# LQN-02: deterministic NL summary
|
|
1263
1284
|
sm.project_summary = ProjectSummarizer(target).generate(sm)
|
|
@@ -1356,32 +1377,58 @@ def main(
|
|
|
1356
1377
|
_is_contract_mode = mode in ("contract", "standard")
|
|
1357
1378
|
if _is_contract_mode:
|
|
1358
1379
|
from sourcecode.contract_pipeline import ContractPipeline
|
|
1380
|
+
from sourcecode.contract_model import ContractSummary as _ContractSummary
|
|
1359
1381
|
_cp = ContractPipeline()
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1382
|
+
try:
|
|
1383
|
+
_contracts, _contract_summary = _cp.run(
|
|
1384
|
+
target,
|
|
1385
|
+
sm.file_paths,
|
|
1386
|
+
entry_points=sm.entry_points,
|
|
1387
|
+
monorepo_packages=sm.monorepo_packages,
|
|
1388
|
+
mode=mode,
|
|
1389
|
+
rank_by=rank_by, # type: ignore[arg-type]
|
|
1390
|
+
max_symbols=max_symbols,
|
|
1391
|
+
dependency_depth=dependency_depth,
|
|
1392
|
+
entrypoints_only=entrypoints_only,
|
|
1393
|
+
changed_only=changed_only,
|
|
1394
|
+
symbol=symbol,
|
|
1395
|
+
compress_types=compress_types,
|
|
1396
|
+
max_importers=max_importers,
|
|
1397
|
+
semantic_calls=sm.semantic_calls or None,
|
|
1398
|
+
code_notes=sm.code_notes or None,
|
|
1399
|
+
)
|
|
1400
|
+
except Exception as _exc:
|
|
1401
|
+
typer.echo(f"[error] contract pipeline failed: {_exc}", err=True)
|
|
1402
|
+
_contracts = []
|
|
1403
|
+
_contract_summary = _ContractSummary(
|
|
1404
|
+
mode=mode,
|
|
1405
|
+
total_files=0,
|
|
1406
|
+
extracted_files=0,
|
|
1407
|
+
filtered_files=0,
|
|
1408
|
+
method_breakdown={},
|
|
1409
|
+
ranked_by=rank_by,
|
|
1410
|
+
limitations=[f"pipeline_error: {type(_exc).__name__}"],
|
|
1411
|
+
)
|
|
1377
1412
|
sm = _replace(sm, file_contracts=_contracts, contract_summary=_contract_summary)
|
|
1378
1413
|
if symbol is not None and len(_contracts) == 0:
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1414
|
+
_jvm_stacks = {"java", "kotlin", "scala", "groovy"}
|
|
1415
|
+
_is_jvm_repo = any(s.stack in _jvm_stacks for s in sm.stacks)
|
|
1416
|
+
if _is_jvm_repo:
|
|
1417
|
+
typer.echo(
|
|
1418
|
+
f"[warning] --symbol '{symbol}' matched 0 files. "
|
|
1419
|
+
"Per-file AST extraction is not available for Java/JVM repos — "
|
|
1420
|
+
"symbol search works only with Python, TypeScript, and JavaScript. "
|
|
1421
|
+
"Use --git-context or --code-notes for JVM navigation.",
|
|
1422
|
+
err=True,
|
|
1423
|
+
)
|
|
1424
|
+
else:
|
|
1425
|
+
typer.echo(
|
|
1426
|
+
f"[warning] --symbol '{symbol}' matched 0 files. "
|
|
1427
|
+
"The symbol may not exist, the name may differ in case, "
|
|
1428
|
+
"or the file may be outside the scanned depth. "
|
|
1429
|
+
"Try --depth 8 or verify the symbol name.",
|
|
1430
|
+
err=True,
|
|
1431
|
+
)
|
|
1385
1432
|
if agent:
|
|
1386
1433
|
typer.echo(f"[contract] {len(_contracts)} files extracted ({_contract_summary.method_breakdown})", err=True)
|
|
1387
1434
|
|
sourcecode/contract_pipeline.py
CHANGED
|
@@ -241,7 +241,9 @@ class ContractPipeline:
|
|
|
241
241
|
contracts.append(contract)
|
|
242
242
|
method_counts[contract.extraction_method] += 1
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
_js_ts_languages = {"typescript", "javascript", "tsx", "jsx"}
|
|
245
|
+
_has_js_ts = any(c.language in _js_ts_languages for c in contracts)
|
|
246
|
+
if _has_js_ts and not self._extractor.has_tree_sitter():
|
|
245
247
|
limitations.append(
|
|
246
248
|
"tree_sitter_unavailable: JS/TS extraction uses heuristics. "
|
|
247
249
|
"Install with: pip install 'sourcecode[ast]'"
|
|
@@ -66,6 +66,13 @@ class HeuristicDetector(AbstractDetector):
|
|
|
66
66
|
counts[stack] += 1
|
|
67
67
|
break
|
|
68
68
|
|
|
69
|
+
# Suppress minority stacks: if a language appears in fewer than 3 files
|
|
70
|
+
# AND represents less than 10% of detected source files, it is likely
|
|
71
|
+
# noise (stray config files, vendored snippets) rather than a real stack.
|
|
72
|
+
# Always emit the dominant language regardless of absolute count.
|
|
73
|
+
total_detected = sum(counts.values())
|
|
74
|
+
_ABS_MIN = 3
|
|
75
|
+
_REL_MIN = 0.10
|
|
69
76
|
stacks = [
|
|
70
77
|
StackDetection(
|
|
71
78
|
stack=stack,
|
|
@@ -73,7 +80,8 @@ class HeuristicDetector(AbstractDetector):
|
|
|
73
80
|
confidence="low",
|
|
74
81
|
manifests=[],
|
|
75
82
|
)
|
|
76
|
-
for stack,
|
|
83
|
+
for stack, count in counts.most_common()
|
|
84
|
+
if count >= _ABS_MIN or (total_detected > 0 and count / total_detected >= _REL_MIN)
|
|
77
85
|
]
|
|
78
86
|
|
|
79
87
|
entry_points: list[EntryPoint] = []
|
sourcecode/env_analyzer.py
CHANGED
|
@@ -11,8 +11,8 @@ _MAX_FILE_SIZE = 512 * 1024 # 512 KB
|
|
|
11
11
|
|
|
12
12
|
_SKIP_DIRS = {
|
|
13
13
|
"node_modules", ".git", "__pycache__", ".venv", "venv",
|
|
14
|
-
".mypy_cache", "dist", "build", "
|
|
15
|
-
".next", ".nuxt", ".output", "vendor",
|
|
14
|
+
".mypy_cache", "dist", "build", "target", ".gradle",
|
|
15
|
+
".tox", ".eggs", "coverage", ".next", ".nuxt", ".output", "vendor",
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
_CODE_EXTENSIONS = {
|
sourcecode/serializer.py
CHANGED
|
@@ -121,10 +121,16 @@ def _dependency_groups(sm: SourceMap) -> dict[str, list[dict[str, Any]]]:
|
|
|
121
121
|
|
|
122
122
|
if role in _PRODUCTION_DEP_ROLES and scope not in {"dev"}:
|
|
123
123
|
groups["production_dependencies"].append(item)
|
|
124
|
+
_jvm_ecosystems = {"maven", "gradle", "java", "kotlin", "scala", "groovy"}
|
|
124
125
|
if dep.source == "manifest" and name_key not in import_index:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
if dep.ecosystem in _jvm_ecosystems:
|
|
127
|
+
# Static import check unsupported for JVM: import index only covers
|
|
128
|
+
# Python/JS/TS. Flagging JVM deps as suspicious produces only false positives.
|
|
129
|
+
pass
|
|
130
|
+
else:
|
|
131
|
+
suspect = dict(item)
|
|
132
|
+
suspect["reason"] = "declared as production dependency but no static import observed"
|
|
133
|
+
groups["suspicious_dependencies"].append(suspect)
|
|
128
134
|
elif role in _TEST_DEP_ROLES:
|
|
129
135
|
groups["test_utilities"].append(item)
|
|
130
136
|
elif role in _BUILD_DEP_ROLES:
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=GGAUffktLLZY15PHqWZ0id9C28zA6fs7XQ7oxyKmNT0,103
|
|
2
2
|
sourcecode/adaptive_scanner.py,sha256=6dh34C2qZXyRbw-8xBhbEwDdXanM6CRFRWayVoYITnA,10190
|
|
3
3
|
sourcecode/architecture_analyzer.py,sha256=O4AXc7l_WTzIXrcAzstqZy-TGKNaFa6p3MzpgVjaO8g,27749
|
|
4
4
|
sourcecode/architecture_summary.py,sha256=rSY5MRiaz4N1YdG0pqDTDuFjSN7PO_Zplx-dtNzv2Yo,19985
|
|
5
5
|
sourcecode/ast_extractor.py,sha256=0OHQwTUBBc9lmqPLryVeB1z8dGIC6NhLlar800CD9oI,41129
|
|
6
6
|
sourcecode/classifier.py,sha256=GKTMN8qKZX7ponSwDJfN08RrasI4CVpq1_gFBgEopps,7093
|
|
7
|
-
sourcecode/cli.py,sha256=
|
|
7
|
+
sourcecode/cli.py,sha256=pjBq-ZIWqoBbESWorW2d0kIGtkby9urt_38ACCKqK1Q,71026
|
|
8
8
|
sourcecode/code_notes_analyzer.py,sha256=rRd8bFYV0krjlxxQV0wenwE9K7pVpUQSR7KvSvUQKw4,9226
|
|
9
9
|
sourcecode/confidence_analyzer.py,sha256=HxJMPLI5ulqtkncnv98W4iVO6yMbpQo87VuxiuNbDmY,12167
|
|
10
10
|
sourcecode/context_scorer.py,sha256=nhppAo80fblAqcB9Ns0iQd21TZUrl2mQMo_xzPgavRE,14679
|
|
11
11
|
sourcecode/context_summarizer.py,sha256=CiQrfBEzun949bWvmLabWoj2HhPn6Lw62ofqnsy0FlQ,6503
|
|
12
12
|
sourcecode/contract_model.py,sha256=gCf9-Kj0G7l0lvRTAcRfFAfMgs1Rpizv4mKovQLYUkw,3434
|
|
13
|
-
sourcecode/contract_pipeline.py,sha256=
|
|
13
|
+
sourcecode/contract_pipeline.py,sha256=wWkm0_zScUy-Q-mrAG57qysYxjNPOybjObxpwp859e0,24615
|
|
14
14
|
sourcecode/coverage_parser.py,sha256=q0LeZJaX1bnntLu-ImksdBsMlpsVmk_iUfSaB4eaJGo,19702
|
|
15
15
|
sourcecode/dependency_analyzer.py,sha256=Exq0BfInvfS5iAg9xAr6WI2uPNuotkIudTKcYJcRhB8,52757
|
|
16
16
|
sourcecode/doc_analyzer.py,sha256=TttdS7mndKQhyJCfJnnAsyGCJrf-TIL7oXxDlTLUFKE,21248
|
|
17
17
|
sourcecode/entrypoint_classifier.py,sha256=a69dMGyxCTd_LOm3oqj-EXWpRmbmeujN7T1mr2eJ1as,3877
|
|
18
|
-
sourcecode/env_analyzer.py,sha256=
|
|
18
|
+
sourcecode/env_analyzer.py,sha256=YXlaxFBuf-ladWmb3iLCNMN-rKhP2JuqAIDwZdiIZHQ,18473
|
|
19
19
|
sourcecode/file_classifier.py,sha256=_KfFIIolharaIxbSTrCkaWauQIqNHCyor_n47RGyDh8,8577
|
|
20
20
|
sourcecode/git_analyzer.py,sha256=PD3eNWydznQ6KLNpxGzBqizIHoPIKevfwz9Xyf_pDt4,11600
|
|
21
21
|
sourcecode/graph_analyzer.py,sha256=hMOsLLz9B0UnQ4xwbHdgr3bFvqpw0bQ8kN-xmEn3Krk,64156
|
|
@@ -29,7 +29,7 @@ sourcecode/runtime_classifier.py,sha256=zWX3r3HCKHc-qtIobErOa8aKMmaoPYREtJKvPcBG
|
|
|
29
29
|
sourcecode/scanner.py,sha256=aM3h9-DCQ3xKpeHpHYdo2vX6T5P95HA_YwZbkAVNwmo,8288
|
|
30
30
|
sourcecode/schema.py,sha256=ofEge9hTWHOTjeWt7ceCDQWzP-uhhenrYX2usjW2KVU,22759
|
|
31
31
|
sourcecode/semantic_analyzer.py,sha256=16EFTgM7ooW0m5gNUKOlTSn7IEMLSzKmzQn-cWaSqjs,82604
|
|
32
|
-
sourcecode/serializer.py,sha256=
|
|
32
|
+
sourcecode/serializer.py,sha256=CBK_i1joiNl8aCjFgnyIMrEFhAVCAk_ltfOqot2yVC4,59361
|
|
33
33
|
sourcecode/summarizer.py,sha256=ZuzIdm3t8A-d5MuQL0TSNLrd-L0IQIuguIxeNXMNJf8,16070
|
|
34
34
|
sourcecode/tree_utils.py,sha256=Fj9OIuUksBvgibNd3feog0sMDjVypJzPexp5lvMoYWI,1424
|
|
35
35
|
sourcecode/workspace.py,sha256=fQlVoNx8S-fSHpKoJ0JBvEHCFkxszH0KZVJed1i3TRk,6845
|
|
@@ -40,7 +40,7 @@ sourcecode/detectors/dart.py,sha256=QbqaL5v18-_ort75HihVBt8MsKUfOcFDF8IpWFLiXpI,
|
|
|
40
40
|
sourcecode/detectors/dotnet.py,sha256=oi8zq3AfUItlK3h_qM81vOe1ZVTIU9LBKIlIrRDuqOs,6864
|
|
41
41
|
sourcecode/detectors/elixir.py,sha256=jCpvt5Yi6jvplc80ovRtWh17q-11ZGo9qX7o8b57TJE,1713
|
|
42
42
|
sourcecode/detectors/go.py,sha256=2r66uRQfeTWsqxr4HDhT6vExZErby0t46QXLHVBRv9w,2782
|
|
43
|
-
sourcecode/detectors/heuristic.py,sha256=
|
|
43
|
+
sourcecode/detectors/heuristic.py,sha256=bCqqgbHavl4Sse3dqT8mwmo1wAdgeJr7VyXOmfClLKo,3387
|
|
44
44
|
sourcecode/detectors/hybrid.py,sha256=IGFRUVsAZ1ooRlFdznCeJAV6vy1yVDx-VyghvLtddXc,9101
|
|
45
45
|
sourcecode/detectors/java.py,sha256=cZvB13cqJ76zHDncEG-TOCuK8gJjJN2mZGS2DGEcZy8,7715
|
|
46
46
|
sourcecode/detectors/jvm_ext.py,sha256=EgHJ5W8EE-ZTN9V607mVzohyKgZE8Mc2jCi-DF8RAZU,2616
|
|
@@ -60,8 +60,8 @@ sourcecode/telemetry/consent.py,sha256=wLMvGNJeSSyZoNkQXpoUioY6mMv4Qdvuw7S9jAEWn
|
|
|
60
60
|
sourcecode/telemetry/events.py,sha256=oEvvulfsv5GIDWG2174gSS6tNB95w38AIYiYeifGKlE,2294
|
|
61
61
|
sourcecode/telemetry/filters.py,sha256=Asa71oRl7q3Wt_FMwuufIZJFzSYdgRNKS8LHCIyFeYE,4805
|
|
62
62
|
sourcecode/telemetry/transport.py,sha256=KJeIPCPWMdmbCP3ySGs2iUlia34U6vWne2dZsUezesw,1560
|
|
63
|
-
sourcecode-0.
|
|
64
|
-
sourcecode-0.
|
|
65
|
-
sourcecode-0.
|
|
66
|
-
sourcecode-0.
|
|
67
|
-
sourcecode-0.
|
|
63
|
+
sourcecode-0.45.0.dist-info/METADATA,sha256=KxuymZTpmCBseOiKT5iavKPp7S2zJaYxpB11QEQqnjk,25209
|
|
64
|
+
sourcecode-0.45.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
65
|
+
sourcecode-0.45.0.dist-info/entry_points.txt,sha256=ex3F9rmbXeyDIoFQHtkEqTsKSaJow8F0LrVu8XfIktQ,57
|
|
66
|
+
sourcecode-0.45.0.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
|
|
67
|
+
sourcecode-0.45.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|