sourcecode 0.8.0__tar.gz → 0.9.0__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 (98) hide show
  1. {sourcecode-0.8.0 → sourcecode-0.9.0}/PKG-INFO +1 -1
  2. {sourcecode-0.8.0 → sourcecode-0.9.0}/docs/schema.md +2 -2
  3. {sourcecode-0.8.0 → sourcecode-0.9.0}/pyproject.toml +1 -1
  4. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/__init__.py +1 -1
  5. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/cli.py +49 -0
  6. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/schema.py +65 -0
  7. sourcecode-0.9.0/src/sourcecode/semantic_analyzer.py +1887 -0
  8. sourcecode-0.9.0/tests/test_integration_semantics.py +185 -0
  9. sourcecode-0.9.0/tests/test_semantic_analyzer_node.py +493 -0
  10. sourcecode-0.9.0/tests/test_semantic_analyzer_python.py +302 -0
  11. sourcecode-0.9.0/tests/test_semantic_import_resolution.py +355 -0
  12. sourcecode-0.9.0/tests/test_semantic_schema.py +129 -0
  13. {sourcecode-0.8.0 → sourcecode-0.9.0}/.gitignore +0 -0
  14. {sourcecode-0.8.0 → sourcecode-0.9.0}/.ruff.toml +0 -0
  15. {sourcecode-0.8.0 → sourcecode-0.9.0}/README.md +0 -0
  16. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/classifier.py +0 -0
  17. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/coverage_parser.py +0 -0
  18. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/dependency_analyzer.py +0 -0
  19. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/__init__.py +0 -0
  20. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/base.py +0 -0
  21. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/dart.py +0 -0
  22. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/dotnet.py +0 -0
  23. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/elixir.py +0 -0
  24. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/go.py +0 -0
  25. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/heuristic.py +0 -0
  26. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/java.py +0 -0
  27. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  28. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/nodejs.py +0 -0
  29. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/parsers.py +0 -0
  30. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/php.py +0 -0
  31. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/project.py +0 -0
  32. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/python.py +0 -0
  33. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/ruby.py +0 -0
  34. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/rust.py +0 -0
  35. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/systems.py +0 -0
  36. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/terraform.py +0 -0
  37. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/tooling.py +0 -0
  38. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/doc_analyzer.py +0 -0
  39. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/graph_analyzer.py +0 -0
  40. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/metrics_analyzer.py +0 -0
  41. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/redactor.py +0 -0
  42. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/scanner.py +0 -0
  43. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/serializer.py +0 -0
  44. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/summarizer.py +0 -0
  45. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/tree_utils.py +0 -0
  46. {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/workspace.py +0 -0
  47. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/__init__.py +0 -0
  48. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/conftest.py +0 -0
  49. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/coverage.xml +0 -0
  50. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  51. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
  52. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  53. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/go_service/go.mod +0 -0
  54. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/jacoco.xml +0 -0
  55. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/lcov.info +0 -0
  56. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  57. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/nextjs_app/package.json +0 -0
  58. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  59. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  60. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  61. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  62. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  63. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  64. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_classifier.py +0 -0
  65. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_cli.py +0 -0
  66. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_coverage_parser.py +0 -0
  67. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_dependency_analyzer_node_python.py +0 -0
  68. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
  69. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_dependency_schema.py +0 -0
  70. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_go_rust_java.py +0 -0
  71. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_nodejs.py +0 -0
  72. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_php_ruby_dart.py +0 -0
  73. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_python.py +0 -0
  74. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_universal_managed.py +0 -0
  75. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_universal_systems.py +0 -0
  76. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detectors_base.py +0 -0
  77. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_doc_analyzer_jsdom.py +0 -0
  78. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_doc_analyzer_python.py +0 -0
  79. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_graph_analyzer_polyglot.py +0 -0
  80. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_graph_analyzer_python_node.py +0 -0
  81. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_graph_schema.py +0 -0
  82. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration.py +0 -0
  83. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_dependencies.py +0 -0
  84. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_detection.py +0 -0
  85. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_docs.py +0 -0
  86. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_graph_modules.py +0 -0
  87. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_lqn.py +0 -0
  88. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_metrics.py +0 -0
  89. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_multistack.py +0 -0
  90. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_universal.py +0 -0
  91. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_metrics_analyzer.py +0 -0
  92. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_packaging.py +0 -0
  93. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_real_projects.py +0 -0
  94. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_redactor.py +0 -0
  95. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_scanner.py +0 -0
  96. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_schema.py +0 -0
  97. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_summarizer.py +0 -0
  98. {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_workspace_analyzer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Genera un mapa de contexto estructurado de proyectos de software para agentes IA
5
5
  License: MIT
6
6
  Requires-Python: >=3.9
@@ -61,7 +61,7 @@ Campos:
61
61
  {
62
62
  "schema_version": "1.0",
63
63
  "generated_at": "2026-04-07T19:41:05.686277+00:00",
64
- "sourcecode_version": "0.8.0",
64
+ "sourcecode_version": "0.9.0",
65
65
  "analyzed_path": "/abs/path/to/project"
66
66
  }
67
67
  ```
@@ -582,7 +582,7 @@ Ejemplo de salida para un monorepo con web Node.js y API Python con `--dependenc
582
582
  "metadata": {
583
583
  "schema_version": "1.0",
584
584
  "generated_at": "2026-04-07T19:41:05.686277+00:00",
585
- "sourcecode_version": "0.8.0",
585
+ "sourcecode_version": "0.9.0",
586
586
  "analyzed_path": "/abs/path/to/project"
587
587
  },
588
588
  "file_tree": {
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "0.8.0"
7
+ version = "0.9.0"
8
8
  description = "Genera un mapa de contexto estructurado de proyectos de software para agentes IA"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Genera mapas de contexto estructurado para agentes IA."""
2
2
 
3
- __version__ = "0.8.0"
3
+ __version__ = "0.9.0"
@@ -112,6 +112,11 @@ def main(
112
112
  "--full-metrics",
113
113
  help="Incluir metricas de calidad: LOC, simbolos, complejidad, tests y cobertura por fichero",
114
114
  ),
115
+ semantics: bool = typer.Option(
116
+ False,
117
+ "--semantics",
118
+ help="Incluir call graph semantico, linking cross-file de simbolos y resolucion avanzada de imports",
119
+ ),
115
120
  ) -> None:
116
121
  """Genera un mapa de contexto estructurado del proyecto en formato JSON o YAML."""
117
122
  # Validar formato
@@ -228,6 +233,9 @@ def main(
228
233
  doc_analyzer = DocAnalyzer() if docs else None
229
234
  metrics_analyzer = MetricsAnalyzer() if full_metrics else None
230
235
 
236
+ from sourcecode.semantic_analyzer import SemanticAnalyzer
237
+ semantic_analyzer = SemanticAnalyzer() if semantics else None
238
+
231
239
  root_manifests = [
232
240
  manifest
233
241
  for manifest in manifests
@@ -424,6 +432,47 @@ def main(
424
432
  metrics_summary=metrics_summary,
425
433
  )
426
434
 
435
+ # Semantic analysis (--semantics flag)
436
+ if semantic_analyzer is not None:
437
+ if workspace_analysis.workspaces:
438
+ all_sem_calls: list[Any] = []
439
+ all_sem_symbols: list[Any] = []
440
+ all_sem_links: list[Any] = []
441
+ all_sem_summaries: list[Any] = []
442
+ for ws in workspace_analysis.workspaces:
443
+ ws_calls, ws_syms, ws_links, ws_sum = semantic_analyzer.analyze(
444
+ target / ws.path,
445
+ (
446
+ filter_sensitive_files(
447
+ FileScanner(target / ws.path, max_depth=depth).scan_tree()
448
+ )
449
+ ),
450
+ workspace=ws.path,
451
+ )
452
+ all_sem_calls.extend(ws_calls)
453
+ all_sem_symbols.extend(ws_syms)
454
+ all_sem_links.extend(ws_links)
455
+ all_sem_summaries.append(ws_sum)
456
+ merged_sem = semantic_analyzer.merge_summaries(all_sem_summaries)
457
+ sm = replace(
458
+ sm,
459
+ semantic_calls=all_sem_calls,
460
+ semantic_symbols=all_sem_symbols,
461
+ semantic_links=all_sem_links,
462
+ semantic_summary=merged_sem,
463
+ )
464
+ else:
465
+ sem_calls, sem_syms, sem_links, sem_sum = semantic_analyzer.analyze(
466
+ target, file_tree
467
+ )
468
+ sm = replace(
469
+ sm,
470
+ semantic_calls=sem_calls,
471
+ semantic_symbols=sem_syms,
472
+ semantic_links=sem_links,
473
+ semantic_summary=sem_sum,
474
+ )
475
+
427
476
  # Phase 9: LLM Output Quality — poblar campos derivados
428
477
  from sourcecode.summarizer import ProjectSummarizer
429
478
  from sourcecode.tree_utils import flatten_file_tree
@@ -236,6 +236,66 @@ class DocSummary:
236
236
  limitations: list[str] = field(default_factory=list)
237
237
 
238
238
 
239
+ @dataclass
240
+ class SymbolRecord:
241
+ """Symbol definition found in a source file."""
242
+
243
+ symbol: str # local name: "MyClass" or "my_func"
244
+ kind: str # "function" | "class" | "constant" | "method"
245
+ language: str
246
+ path: str # relative path to defining file
247
+ line: Optional[int] = None
248
+ qualified_name: Optional[str] = None # "pkg.module.MyClass"
249
+ exported: bool = True # False if name starts with _ and no __all__ override
250
+ workspace: Optional[str] = None
251
+
252
+
253
+ @dataclass
254
+ class CallRecord:
255
+ """A resolved call from one symbol to another, possibly across files."""
256
+
257
+ caller_path: str
258
+ caller_symbol: str
259
+ callee_path: str
260
+ callee_symbol: str
261
+ call_line: Optional[int] = None
262
+ confidence: Literal["high", "medium", "low"] = "medium"
263
+ method: Literal["ast", "heuristic", "unresolved"] = "heuristic"
264
+ args: list[str] = field(default_factory=list)
265
+ kwargs: dict[str, str] = field(default_factory=dict)
266
+ workspace: Optional[str] = None
267
+
268
+
269
+ @dataclass
270
+ class SymbolLink:
271
+ """A symbol imported in one file, resolved to its definition in another."""
272
+
273
+ importer_path: str
274
+ symbol: str
275
+ source_path: Optional[str] = None
276
+ source_line: Optional[int] = None
277
+ is_external: bool = False
278
+ confidence: Literal["high", "medium", "low"] = "high"
279
+ method: Literal["ast", "heuristic", "unresolved"] = "ast"
280
+ workspace: Optional[str] = None
281
+
282
+
283
+ @dataclass
284
+ class SemanticSummary:
285
+ """Summary of the --semantics analysis."""
286
+
287
+ requested: bool = False
288
+ call_count: int = 0
289
+ symbol_count: int = 0
290
+ link_count: int = 0
291
+ languages: list[str] = field(default_factory=list)
292
+ language_coverage: dict[str, str] = field(default_factory=dict)
293
+ files_analyzed: int = 0
294
+ files_skipped: int = 0
295
+ truncated: bool = False
296
+ limitations: list[str] = field(default_factory=list)
297
+
298
+
239
299
  @dataclass
240
300
  class SourceMap:
241
301
  """Schema completo del output v1.0.
@@ -266,3 +326,8 @@ class SourceMap:
266
326
  # Phase 10: Code Quality Metrics
267
327
  file_metrics: list[FileMetrics] = field(default_factory=list)
268
328
  metrics_summary: Optional[MetricsSummary] = None
329
+ # Phase 12: Static Semantics
330
+ semantic_calls: list[CallRecord] = field(default_factory=list)
331
+ semantic_symbols: list[SymbolRecord] = field(default_factory=list)
332
+ semantic_links: list[SymbolLink] = field(default_factory=list)
333
+ semantic_summary: Optional[SemanticSummary] = None