sourcecode 0.19.0__tar.gz → 0.20.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.
- {sourcecode-0.19.0 → sourcecode-0.20.0}/PKG-INFO +23 -9
- {sourcecode-0.19.0 → sourcecode-0.20.0}/README.md +22 -8
- {sourcecode-0.19.0 → sourcecode-0.20.0}/docs/schema.md +2 -2
- {sourcecode-0.19.0 → sourcecode-0.20.0}/pyproject.toml +1 -1
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/cli.py +24 -1
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/dependency_analyzer.py +157 -2
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/serializer.py +18 -11
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_dependency_analyzer_node_python.py +2 -2
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_dependencies.py +1 -1
- {sourcecode-0.19.0 → sourcecode-0.20.0}/.gitignore +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/.ruff.toml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/__init__.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/conftest.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/lcov.info +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_architecture_summary.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_classifier.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_cli.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_coverage_parser.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_cross_consistency.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_dependency_schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_detector_python.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_detectors_base.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_graph_schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_detection.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_docs.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_lqn.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_metrics.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_multistack.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_semantics.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_integration_universal.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_packaging.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_real_projects.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_redactor.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_scanner.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_schema_normalization.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_semantic_schema.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.0}/tests/test_summarizer.py +0 -0
- {sourcecode-0.19.0 → sourcecode-0.20.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.
|
|
3
|
+
Version: 0.20.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
|
|
@@ -81,7 +81,7 @@ sourcecode --version
|
|
|
81
81
|
|
|
82
82
|
## What It Detects
|
|
83
83
|
|
|
84
|
-
- Stacks: Node.js, Python, Go, Rust, Java, PHP, Ruby, and Dart.
|
|
84
|
+
- Stacks: Node.js, Python, Go, Rust, Java (Maven `pom.xml` and Gradle `build.gradle`/`build.gradle.kts`), PHP, Ruby, and Dart.
|
|
85
85
|
- Frameworks associated with each stack when enough signals are present.
|
|
86
86
|
- `project_type`: `webapp`, `api`, `library`, `cli`, `fullstack`, `monorepo`, or `unknown`.
|
|
87
87
|
- Relevant `entry_points`, such as `main.py`, `cmd/api/main.go`, or `app/page.tsx`.
|
|
@@ -111,6 +111,8 @@ sourcecode --version
|
|
|
111
111
|
| `--env-map` | off | Map all environment variables referenced in source code: key name, required/optional status, inferred type (`string`, `int`, `bool`, `url`, `path`, `enum`), functional category (`database`, `auth`, `cache`, `storage`, `service`, `observability`, `feature_flag`, `server`, `general`), default value when present, and source file locations. Supplements with descriptions from `.env.example`, `.env.sample`, and similar reference files. |
|
|
112
112
|
| `--code-notes` | off | Extract inline code annotations — `TODO`, `FIXME`, `HACK`, `NOTE`, `DEPRECATED`, `WARNING`, `XXX`, `BUG`, `OPTIMIZE` — with file path, line number, annotation text, and the nearest enclosing function or class. Also detects Architecture Decision Records (ADRs) in `docs/decisions/`, `docs/adr/`, `adr/`, and similar directories, extracting title, status, and summary. |
|
|
113
113
|
| `--depth INTEGER` | `4` | Maximum file tree depth. Range: 1–20. |
|
|
114
|
+
| `--no-tree` | off | Suppress `file_tree`, `file_paths` (and `file_tree_depth1` in `--compact`) from the output. Ideal with `--dependencies` on large projects to get dependency data without a multi-thousand-line file tree. |
|
|
115
|
+
| `--agent` | off | Agent mode: auto-selects `--compact --dependencies --env-map --code-notes` and adds `--no-tree` automatically for Java/Gradle projects or large repositories. Prints selected flags to stderr. Can be combined with other flags (e.g. `--agent --git-context`). |
|
|
114
116
|
| `--no-redact` | off | Disable secret redaction (enabled by default). |
|
|
115
117
|
| `--version` | — | Show version and exit. |
|
|
116
118
|
|
|
@@ -123,8 +125,8 @@ The full schema (`SourceMap`) includes the following fields:
|
|
|
123
125
|
| Field | Type | Description |
|
|
124
126
|
|-------|------|-------------|
|
|
125
127
|
| `metadata` | object | Schema version, timestamp, `sourcecode` version, and analyzed path. |
|
|
126
|
-
| `file_tree` | object | Repository tree where `null` represents a file and `{}` represents a directory. |
|
|
127
|
-
| `file_paths` | array | Flat list of all project paths derived from `file_tree`, with forward-slash separators.
|
|
128
|
+
| `file_tree` | object | Repository tree where `null` represents a file and `{}` represents a directory. Suppressed when `--no-tree` is active. |
|
|
129
|
+
| `file_paths` | array | Flat list of all project paths derived from `file_tree`, with forward-slash separators. Respects `--depth`. Suppressed when `--no-tree` is active. |
|
|
128
130
|
| `project_summary` | string\|null | Deterministic natural-language description of the project. Includes: manifest/README description when available, detected architecture pattern (`layered`, `mvc`, `hexagonal`, `fullstack`), business domain names inferred from directory structure, entry points (when no domains are detected), and dependency count. Present when stacks are detected. |
|
|
129
131
|
| `architecture_summary` | string\|null | Static summary of the main execution flow, orchestrated modules, and output produced by the project. Present when enough structural evidence is available. |
|
|
130
132
|
| `stacks` | array | Stack detections with confidence, frameworks, manifests, `primary`, `root`, `workspace`, and `signals`. |
|
|
@@ -223,7 +225,7 @@ ADR detection looks for Markdown files in `docs/decisions/`, `docs/adr/`, `adr/`
|
|
|
223
225
|
|
|
224
226
|
## Compact Mode
|
|
225
227
|
|
|
226
|
-
`--compact` returns a reduced JSON view optimized for LLM prompts
|
|
228
|
+
`--compact` returns a reduced JSON view optimized for LLM prompts. It excludes the full `dependencies` list, `docs`, and `module_graph`, while retaining the fields most useful for project orientation. When optional flags are also active, their summaries are included: `dependency_summary` + `key_dependencies` (with `--dependencies`), `env_summary` (with `--env-map`), and `code_notes_summary` (with `--code-notes`). Adding `--no-tree` further removes `file_tree_depth1`, bringing the output to ~500-800 tokens depending on how many flags are active.
|
|
227
229
|
|
|
228
230
|
Real output from a Python FastAPI project:
|
|
229
231
|
|
|
@@ -266,7 +268,7 @@ Real output from a Python FastAPI project:
|
|
|
266
268
|
}
|
|
267
269
|
```
|
|
268
270
|
|
|
269
|
-
When `--compact --dependencies` is used, `dependency_summary` is populated
|
|
271
|
+
When `--compact --dependencies` is used, `dependency_summary` is populated and `key_dependencies` lists the top-15 direct dependencies with resolved versions. Add `--no-tree` to drop `file_tree_depth1` for the smallest possible context footprint.
|
|
270
272
|
|
|
271
273
|
## Docs Mode
|
|
272
274
|
|
|
@@ -444,15 +446,27 @@ In a monorepo, each stack includes its own `root` and `workspace`, and one of th
|
|
|
444
446
|
|
|
445
447
|
Different modes optimize for different tradeoffs between context size and depth of information.
|
|
446
448
|
|
|
447
|
-
**`--
|
|
449
|
+
**`--agent` — zero-config mode for AI pipelines**
|
|
450
|
+
|
|
451
|
+
Best for: running `sourcecode` from inside an agent without knowing the project in advance. Auto-selects the right flag combination based on detected stack and project size.
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
sourcecode --agent .
|
|
455
|
+
sourcecode --agent --git-context . # add git context on top of auto-selected flags
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
On a Java/Gradle project the output is: `--compact --dependencies --env-map --code-notes --no-tree` (~800 tokens). On a Node/Python project: same without `--no-tree` (~900 tokens including depth-1 tree). Selected flags are always printed to stderr so the agent can log them.
|
|
459
|
+
|
|
460
|
+
**`--compact` — minimal context**
|
|
448
461
|
|
|
449
462
|
Best for: initial orientation, deciding what to explore next, fast handoffs between agents.
|
|
450
463
|
|
|
451
|
-
Includes: `project_summary
|
|
464
|
+
Includes: `project_summary`, `architecture_summary`, `stacks`, `entry_points`, `file_tree_depth1`, and — when the respective flags are active — `dependency_summary` + `key_dependencies`, `env_summary`, `code_notes_summary`.
|
|
452
465
|
|
|
453
466
|
```bash
|
|
454
467
|
sourcecode --compact .
|
|
455
|
-
sourcecode --compact --dependencies .
|
|
468
|
+
sourcecode --compact --dependencies . # + key dependencies with versions
|
|
469
|
+
sourcecode --compact --dependencies --no-tree . # smallest footprint: no file tree
|
|
456
470
|
```
|
|
457
471
|
|
|
458
472
|
**Full output — deep analysis**
|
|
@@ -65,7 +65,7 @@ sourcecode --version
|
|
|
65
65
|
|
|
66
66
|
## What It Detects
|
|
67
67
|
|
|
68
|
-
- Stacks: Node.js, Python, Go, Rust, Java, PHP, Ruby, and Dart.
|
|
68
|
+
- Stacks: Node.js, Python, Go, Rust, Java (Maven `pom.xml` and Gradle `build.gradle`/`build.gradle.kts`), PHP, Ruby, and Dart.
|
|
69
69
|
- Frameworks associated with each stack when enough signals are present.
|
|
70
70
|
- `project_type`: `webapp`, `api`, `library`, `cli`, `fullstack`, `monorepo`, or `unknown`.
|
|
71
71
|
- Relevant `entry_points`, such as `main.py`, `cmd/api/main.go`, or `app/page.tsx`.
|
|
@@ -95,6 +95,8 @@ sourcecode --version
|
|
|
95
95
|
| `--env-map` | off | Map all environment variables referenced in source code: key name, required/optional status, inferred type (`string`, `int`, `bool`, `url`, `path`, `enum`), functional category (`database`, `auth`, `cache`, `storage`, `service`, `observability`, `feature_flag`, `server`, `general`), default value when present, and source file locations. Supplements with descriptions from `.env.example`, `.env.sample`, and similar reference files. |
|
|
96
96
|
| `--code-notes` | off | Extract inline code annotations — `TODO`, `FIXME`, `HACK`, `NOTE`, `DEPRECATED`, `WARNING`, `XXX`, `BUG`, `OPTIMIZE` — with file path, line number, annotation text, and the nearest enclosing function or class. Also detects Architecture Decision Records (ADRs) in `docs/decisions/`, `docs/adr/`, `adr/`, and similar directories, extracting title, status, and summary. |
|
|
97
97
|
| `--depth INTEGER` | `4` | Maximum file tree depth. Range: 1–20. |
|
|
98
|
+
| `--no-tree` | off | Suppress `file_tree`, `file_paths` (and `file_tree_depth1` in `--compact`) from the output. Ideal with `--dependencies` on large projects to get dependency data without a multi-thousand-line file tree. |
|
|
99
|
+
| `--agent` | off | Agent mode: auto-selects `--compact --dependencies --env-map --code-notes` and adds `--no-tree` automatically for Java/Gradle projects or large repositories. Prints selected flags to stderr. Can be combined with other flags (e.g. `--agent --git-context`). |
|
|
98
100
|
| `--no-redact` | off | Disable secret redaction (enabled by default). |
|
|
99
101
|
| `--version` | — | Show version and exit. |
|
|
100
102
|
|
|
@@ -107,8 +109,8 @@ The full schema (`SourceMap`) includes the following fields:
|
|
|
107
109
|
| Field | Type | Description |
|
|
108
110
|
|-------|------|-------------|
|
|
109
111
|
| `metadata` | object | Schema version, timestamp, `sourcecode` version, and analyzed path. |
|
|
110
|
-
| `file_tree` | object | Repository tree where `null` represents a file and `{}` represents a directory. |
|
|
111
|
-
| `file_paths` | array | Flat list of all project paths derived from `file_tree`, with forward-slash separators.
|
|
112
|
+
| `file_tree` | object | Repository tree where `null` represents a file and `{}` represents a directory. Suppressed when `--no-tree` is active. |
|
|
113
|
+
| `file_paths` | array | Flat list of all project paths derived from `file_tree`, with forward-slash separators. Respects `--depth`. Suppressed when `--no-tree` is active. |
|
|
112
114
|
| `project_summary` | string\|null | Deterministic natural-language description of the project. Includes: manifest/README description when available, detected architecture pattern (`layered`, `mvc`, `hexagonal`, `fullstack`), business domain names inferred from directory structure, entry points (when no domains are detected), and dependency count. Present when stacks are detected. |
|
|
113
115
|
| `architecture_summary` | string\|null | Static summary of the main execution flow, orchestrated modules, and output produced by the project. Present when enough structural evidence is available. |
|
|
114
116
|
| `stacks` | array | Stack detections with confidence, frameworks, manifests, `primary`, `root`, `workspace`, and `signals`. |
|
|
@@ -207,7 +209,7 @@ ADR detection looks for Markdown files in `docs/decisions/`, `docs/adr/`, `adr/`
|
|
|
207
209
|
|
|
208
210
|
## Compact Mode
|
|
209
211
|
|
|
210
|
-
`--compact` returns a reduced JSON view optimized for LLM prompts
|
|
212
|
+
`--compact` returns a reduced JSON view optimized for LLM prompts. It excludes the full `dependencies` list, `docs`, and `module_graph`, while retaining the fields most useful for project orientation. When optional flags are also active, their summaries are included: `dependency_summary` + `key_dependencies` (with `--dependencies`), `env_summary` (with `--env-map`), and `code_notes_summary` (with `--code-notes`). Adding `--no-tree` further removes `file_tree_depth1`, bringing the output to ~500-800 tokens depending on how many flags are active.
|
|
211
213
|
|
|
212
214
|
Real output from a Python FastAPI project:
|
|
213
215
|
|
|
@@ -250,7 +252,7 @@ Real output from a Python FastAPI project:
|
|
|
250
252
|
}
|
|
251
253
|
```
|
|
252
254
|
|
|
253
|
-
When `--compact --dependencies` is used, `dependency_summary` is populated
|
|
255
|
+
When `--compact --dependencies` is used, `dependency_summary` is populated and `key_dependencies` lists the top-15 direct dependencies with resolved versions. Add `--no-tree` to drop `file_tree_depth1` for the smallest possible context footprint.
|
|
254
256
|
|
|
255
257
|
## Docs Mode
|
|
256
258
|
|
|
@@ -428,15 +430,27 @@ In a monorepo, each stack includes its own `root` and `workspace`, and one of th
|
|
|
428
430
|
|
|
429
431
|
Different modes optimize for different tradeoffs between context size and depth of information.
|
|
430
432
|
|
|
431
|
-
**`--
|
|
433
|
+
**`--agent` — zero-config mode for AI pipelines**
|
|
434
|
+
|
|
435
|
+
Best for: running `sourcecode` from inside an agent without knowing the project in advance. Auto-selects the right flag combination based on detected stack and project size.
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
sourcecode --agent .
|
|
439
|
+
sourcecode --agent --git-context . # add git context on top of auto-selected flags
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
On a Java/Gradle project the output is: `--compact --dependencies --env-map --code-notes --no-tree` (~800 tokens). On a Node/Python project: same without `--no-tree` (~900 tokens including depth-1 tree). Selected flags are always printed to stderr so the agent can log them.
|
|
443
|
+
|
|
444
|
+
**`--compact` — minimal context**
|
|
432
445
|
|
|
433
446
|
Best for: initial orientation, deciding what to explore next, fast handoffs between agents.
|
|
434
447
|
|
|
435
|
-
Includes: `project_summary
|
|
448
|
+
Includes: `project_summary`, `architecture_summary`, `stacks`, `entry_points`, `file_tree_depth1`, and — when the respective flags are active — `dependency_summary` + `key_dependencies`, `env_summary`, `code_notes_summary`.
|
|
436
449
|
|
|
437
450
|
```bash
|
|
438
451
|
sourcecode --compact .
|
|
439
|
-
sourcecode --compact --dependencies .
|
|
452
|
+
sourcecode --compact --dependencies . # + key dependencies with versions
|
|
453
|
+
sourcecode --compact --dependencies --no-tree . # smallest footprint: no file tree
|
|
440
454
|
```
|
|
441
455
|
|
|
442
456
|
**Full output — deep analysis**
|
|
@@ -81,7 +81,7 @@ Campos:
|
|
|
81
81
|
{
|
|
82
82
|
"schema_version": "1.0",
|
|
83
83
|
"generated_at": "2026-04-07T19:41:05.686277+00:00",
|
|
84
|
-
"sourcecode_version": "0.
|
|
84
|
+
"sourcecode_version": "0.20.0",
|
|
85
85
|
"analyzed_path": "/abs/path/to/project"
|
|
86
86
|
}
|
|
87
87
|
```
|
|
@@ -645,7 +645,7 @@ Ejemplo de salida para un monorepo con web Node.js y API Python con `--dependenc
|
|
|
645
645
|
"metadata": {
|
|
646
646
|
"schema_version": "1.0",
|
|
647
647
|
"generated_at": "2026-04-07T19:41:05.686277+00:00",
|
|
648
|
-
"sourcecode_version": "0.
|
|
648
|
+
"sourcecode_version": "0.20.0",
|
|
649
649
|
"analyzed_path": "/abs/path/to/project"
|
|
650
650
|
},
|
|
651
651
|
"file_tree": {
|
|
@@ -75,6 +75,11 @@ def main(
|
|
|
75
75
|
"--graph-edges",
|
|
76
76
|
help="Tipos de arista para `--graph-modules` separados por comas: imports,calls,contains,extends",
|
|
77
77
|
),
|
|
78
|
+
no_tree: bool = typer.Option(
|
|
79
|
+
False,
|
|
80
|
+
"--no-tree",
|
|
81
|
+
help="Suprimir file_tree y file_paths del output (ideal con --dependencies en proyectos grandes)",
|
|
82
|
+
),
|
|
78
83
|
no_redact: bool = typer.Option(
|
|
79
84
|
False,
|
|
80
85
|
"--no-redact",
|
|
@@ -151,6 +156,11 @@ def main(
|
|
|
151
156
|
"--code-notes",
|
|
152
157
|
help="Extraer anotaciones TODO/FIXME/HACK/NOTE/DEPRECATED/WARNING/BUG/XXX/OPTIMIZE con ubicacion y simbolo envolvente, y detectar ADRs en docs/decisions/, docs/adr/ y similares",
|
|
153
158
|
),
|
|
159
|
+
agent: bool = typer.Option(
|
|
160
|
+
False,
|
|
161
|
+
"--agent",
|
|
162
|
+
help="Modo agente: selecciona automaticamente --compact --dependencies --env-map --code-notes y activa --no-tree en proyectos Java/Gradle o grandes",
|
|
163
|
+
),
|
|
154
164
|
) -> None:
|
|
155
165
|
"""Genera un mapa de contexto estructurado del proyecto en formato JSON o YAML."""
|
|
156
166
|
# Validar formato
|
|
@@ -221,6 +231,16 @@ def main(
|
|
|
221
231
|
_java_min_depth = 8
|
|
222
232
|
effective_depth = max(depth, _java_min_depth) if _is_java and depth < _java_min_depth else depth
|
|
223
233
|
|
|
234
|
+
# --agent: auto-select flags based on project characteristics
|
|
235
|
+
if agent:
|
|
236
|
+
compact = True
|
|
237
|
+
if _is_java:
|
|
238
|
+
no_tree = True
|
|
239
|
+
_agent_flags = ["--compact", "--dependencies", "--env-map", "--code-notes"]
|
|
240
|
+
if no_tree:
|
|
241
|
+
_agent_flags.append("--no-tree")
|
|
242
|
+
typer.echo(f"[agent] {' '.join(_agent_flags)}", err=True)
|
|
243
|
+
|
|
224
244
|
scanner = FileScanner(target, max_depth=effective_depth)
|
|
225
245
|
raw_tree = scanner.scan_tree()
|
|
226
246
|
|
|
@@ -594,7 +614,7 @@ def main(
|
|
|
594
614
|
|
|
595
615
|
# 4. Serializar (con o sin modo compact)
|
|
596
616
|
if compact:
|
|
597
|
-
data = compact_view(sm)
|
|
617
|
+
data = compact_view(sm, no_tree=no_tree)
|
|
598
618
|
# Aplicar redaccion sobre el dict del compact view
|
|
599
619
|
if not no_redact:
|
|
600
620
|
data = redact_dict(data)
|
|
@@ -602,6 +622,9 @@ def main(
|
|
|
602
622
|
else:
|
|
603
623
|
# Redactar sobre el dict serializado (SEC-01, SEC-03)
|
|
604
624
|
raw_dict = asdict(sm)
|
|
625
|
+
if no_tree:
|
|
626
|
+
raw_dict.pop("file_tree", None)
|
|
627
|
+
raw_dict.pop("file_paths", None)
|
|
605
628
|
if not no_redact:
|
|
606
629
|
raw_dict = redact_dict(raw_dict)
|
|
607
630
|
|
|
@@ -34,6 +34,7 @@ class DependencyAnalyzer:
|
|
|
34
34
|
self._analyze_go,
|
|
35
35
|
self._analyze_dotnet,
|
|
36
36
|
self._analyze_java,
|
|
37
|
+
self._analyze_gradle,
|
|
37
38
|
):
|
|
38
39
|
handler_records, handler_limitations = handler(root)
|
|
39
40
|
records.extend(replace(record, workspace=workspace) for record in handler_records)
|
|
@@ -925,6 +926,47 @@ class DependencyAnalyzer:
|
|
|
925
926
|
result.append(resolved)
|
|
926
927
|
return self._dedupe(result)
|
|
927
928
|
|
|
929
|
+
def _parse_maven_properties(self, root_elem: ET.Element, ns: str) -> dict[str, str]:
|
|
930
|
+
properties: dict[str, str] = {}
|
|
931
|
+
props_elem = root_elem.find(f"{ns}properties")
|
|
932
|
+
if props_elem is not None:
|
|
933
|
+
for prop in props_elem:
|
|
934
|
+
tag = prop.tag.replace(ns, "") if ns else prop.tag
|
|
935
|
+
if prop.text:
|
|
936
|
+
properties[tag] = prop.text.strip()
|
|
937
|
+
return properties
|
|
938
|
+
|
|
939
|
+
def _resolve_maven_version(self, version_raw: Optional[str], properties: dict[str, str]) -> Optional[str]:
|
|
940
|
+
if not version_raw:
|
|
941
|
+
return None
|
|
942
|
+
if not version_raw.startswith("${"):
|
|
943
|
+
return version_raw
|
|
944
|
+
prop_name = version_raw[2:-1] if version_raw.endswith("}") else None
|
|
945
|
+
if prop_name and prop_name in properties:
|
|
946
|
+
return properties[prop_name]
|
|
947
|
+
return None
|
|
948
|
+
|
|
949
|
+
def _parse_dependency_management(
|
|
950
|
+
self, root_elem: ET.Element, ns: str, properties: dict[str, str]
|
|
951
|
+
) -> dict[str, str]:
|
|
952
|
+
dm_versions: dict[str, str] = {}
|
|
953
|
+
dm_elem = root_elem.find(f"{ns}dependencyManagement")
|
|
954
|
+
if dm_elem is None:
|
|
955
|
+
return dm_versions
|
|
956
|
+
deps_elem = dm_elem.find(f"{ns}dependencies")
|
|
957
|
+
if deps_elem is None:
|
|
958
|
+
return dm_versions
|
|
959
|
+
for dep in deps_elem.findall(f"{ns}dependency"):
|
|
960
|
+
group_id = (dep.findtext(f"{ns}groupId") or "").strip()
|
|
961
|
+
artifact_id = (dep.findtext(f"{ns}artifactId") or "").strip()
|
|
962
|
+
if not group_id or not artifact_id:
|
|
963
|
+
continue
|
|
964
|
+
version_raw = (dep.findtext(f"{ns}version") or "").strip() or None
|
|
965
|
+
resolved = self._resolve_maven_version(version_raw, properties)
|
|
966
|
+
if resolved:
|
|
967
|
+
dm_versions[f"{group_id}:{artifact_id}"] = resolved
|
|
968
|
+
return dm_versions
|
|
969
|
+
|
|
928
970
|
def _analyze_java(self, root: Path) -> tuple[list[DependencyRecord], list[str]]:
|
|
929
971
|
pom = root / "pom.xml"
|
|
930
972
|
if not pom.exists():
|
|
@@ -938,6 +980,9 @@ class DependencyAnalyzer:
|
|
|
938
980
|
ns_match = re.match(r"\{[^}]+\}", root_elem.tag)
|
|
939
981
|
ns = ns_match.group(0) if ns_match else ""
|
|
940
982
|
|
|
983
|
+
properties = self._parse_maven_properties(root_elem, ns)
|
|
984
|
+
dm_versions = self._parse_dependency_management(root_elem, ns, properties)
|
|
985
|
+
|
|
941
986
|
records: list[DependencyRecord] = []
|
|
942
987
|
deps_elem = root_elem.find(f"{ns}dependencies")
|
|
943
988
|
if deps_elem is None:
|
|
@@ -949,8 +994,9 @@ class DependencyAnalyzer:
|
|
|
949
994
|
if not group_id or not artifact_id:
|
|
950
995
|
continue
|
|
951
996
|
version_raw = (dep.findtext(f"{ns}version") or "").strip() or None
|
|
952
|
-
|
|
953
|
-
|
|
997
|
+
declared = self._resolve_maven_version(version_raw, properties)
|
|
998
|
+
if declared is None:
|
|
999
|
+
declared = dm_versions.get(f"{group_id}:{artifact_id}")
|
|
954
1000
|
scope_text = (dep.findtext(f"{ns}scope") or "compile").strip().lower()
|
|
955
1001
|
scope = "dev" if scope_text == "test" else "direct"
|
|
956
1002
|
records.append(
|
|
@@ -969,6 +1015,115 @@ class DependencyAnalyzer:
|
|
|
969
1015
|
limitations.append("java: pom.xml sin dependencias parseables (puede usar BOM o propiedades)")
|
|
970
1016
|
return records, limitations
|
|
971
1017
|
|
|
1018
|
+
def _analyze_gradle(self, root: Path) -> tuple[list[DependencyRecord], list[str]]:
|
|
1019
|
+
for filename in ("build.gradle", "build.gradle.kts"):
|
|
1020
|
+
gradle_file = root / filename
|
|
1021
|
+
if gradle_file.exists():
|
|
1022
|
+
try:
|
|
1023
|
+
content = gradle_file.read_text(encoding="utf-8", errors="replace")
|
|
1024
|
+
except OSError:
|
|
1025
|
+
return [], [f"gradle: error al leer {filename}"]
|
|
1026
|
+
props = self._parse_gradle_properties(root, content)
|
|
1027
|
+
records = self._parse_gradle_dependencies(content, props, filename)
|
|
1028
|
+
return records, ["gradle: sin lockfile compatible; dependencias transitivas no disponibles"]
|
|
1029
|
+
return [], []
|
|
1030
|
+
|
|
1031
|
+
def _parse_gradle_properties(self, root: Path, content: str) -> dict[str, str]:
|
|
1032
|
+
props: dict[str, str] = {}
|
|
1033
|
+
# gradle.properties file (key=value format)
|
|
1034
|
+
gp = root / "gradle.properties"
|
|
1035
|
+
if gp.exists():
|
|
1036
|
+
try:
|
|
1037
|
+
for line in gp.read_text(encoding="utf-8", errors="replace").splitlines():
|
|
1038
|
+
stripped = line.strip()
|
|
1039
|
+
if stripped and not stripped.startswith("#") and "=" in stripped:
|
|
1040
|
+
k, _, v = stripped.partition("=")
|
|
1041
|
+
props[k.strip()] = v.strip()
|
|
1042
|
+
except OSError:
|
|
1043
|
+
pass
|
|
1044
|
+
# Variables declared in the build file itself.
|
|
1045
|
+
# Match: val/var/def x = "v", or bare x = "v" anywhere (ext blocks, top-level).
|
|
1046
|
+
# Negative lookbehind (?<![.\w]) prevents matching mid-expression (e.g. obj.field = "v").
|
|
1047
|
+
for m in re.finditer(r"""(?:(?:val|var|def)\s+)?(?<![.\w])(\w+)\s*=\s*["']([^"']+)["']""", content):
|
|
1048
|
+
props.setdefault(m.group(1), m.group(2))
|
|
1049
|
+
return props
|
|
1050
|
+
|
|
1051
|
+
def _resolve_gradle_version(self, version_raw: Optional[str], props: dict[str, str]) -> Optional[str]:
|
|
1052
|
+
if not version_raw:
|
|
1053
|
+
return None
|
|
1054
|
+
# ${varName} — Groovy string interpolation
|
|
1055
|
+
m = re.fullmatch(r"\$\{(\w+)\}", version_raw)
|
|
1056
|
+
if m:
|
|
1057
|
+
return props.get(m.group(1))
|
|
1058
|
+
# $varName — Kotlin string interpolation
|
|
1059
|
+
m = re.fullmatch(r"\$(\w+)", version_raw)
|
|
1060
|
+
if m:
|
|
1061
|
+
return props.get(m.group(1))
|
|
1062
|
+
return version_raw
|
|
1063
|
+
|
|
1064
|
+
def _parse_gradle_dependencies(
|
|
1065
|
+
self, content: str, props: dict[str, str], manifest_path: str
|
|
1066
|
+
) -> list[DependencyRecord]:
|
|
1067
|
+
_DIRECT = frozenset({
|
|
1068
|
+
"implementation", "api", "compileOnly", "runtimeOnly", "compile", "provided",
|
|
1069
|
+
"compileClasspath", "runtimeClasspath",
|
|
1070
|
+
})
|
|
1071
|
+
_DEV = frozenset({
|
|
1072
|
+
"testImplementation", "testRuntimeOnly", "testCompileOnly", "testApi",
|
|
1073
|
+
"testCompile", "androidTestImplementation", "annotationProcessor", "kapt",
|
|
1074
|
+
"debugImplementation", "releaseImplementation",
|
|
1075
|
+
})
|
|
1076
|
+
all_scopes = _DIRECT | _DEV
|
|
1077
|
+
records: list[DependencyRecord] = []
|
|
1078
|
+
|
|
1079
|
+
# String notation: scope("group:artifact") or scope("group:artifact:version")
|
|
1080
|
+
str_pat = re.compile(
|
|
1081
|
+
r"""(\w+)\s*\(?\s*["']([A-Za-z][\w.\-]*:[A-Za-z][\w.\-]*)(?::([^"'\s)]+))?["']"""
|
|
1082
|
+
)
|
|
1083
|
+
for m in str_pat.finditer(content):
|
|
1084
|
+
scope_kw = m.group(1)
|
|
1085
|
+
if scope_kw not in all_scopes:
|
|
1086
|
+
continue
|
|
1087
|
+
parts = m.group(2).split(":")
|
|
1088
|
+
if len(parts) < 2:
|
|
1089
|
+
continue
|
|
1090
|
+
group_id, artifact_id = parts[0].strip(), parts[1].strip()
|
|
1091
|
+
if not group_id or not artifact_id:
|
|
1092
|
+
continue
|
|
1093
|
+
version = self._resolve_gradle_version(m.group(3), props)
|
|
1094
|
+
records.append(DependencyRecord(
|
|
1095
|
+
name=f"{group_id}:{artifact_id}",
|
|
1096
|
+
ecosystem="java",
|
|
1097
|
+
scope="dev" if scope_kw in _DEV else "direct",
|
|
1098
|
+
declared_version=version,
|
|
1099
|
+
source="manifest",
|
|
1100
|
+
manifest_path=manifest_path,
|
|
1101
|
+
))
|
|
1102
|
+
|
|
1103
|
+
# Map notation: scope(group: "g", name: "a", version: "v") — Groovy uses ':', Kotlin uses '='
|
|
1104
|
+
map_pat = re.compile(
|
|
1105
|
+
r"""(\w+)\s*\(?\s*group\s*[=:]\s*["']([^"']+)["']\s*,\s*name\s*[=:]\s*["']([^"']+)["']"""
|
|
1106
|
+
r"""(?:\s*,\s*version\s*[=:]\s*["']([^"']+)["'])?"""
|
|
1107
|
+
)
|
|
1108
|
+
for m in map_pat.finditer(content):
|
|
1109
|
+
scope_kw = m.group(1)
|
|
1110
|
+
if scope_kw not in all_scopes:
|
|
1111
|
+
continue
|
|
1112
|
+
group_id, artifact_id = m.group(2).strip(), m.group(3).strip()
|
|
1113
|
+
if not group_id or not artifact_id:
|
|
1114
|
+
continue
|
|
1115
|
+
version = self._resolve_gradle_version(m.group(4), props)
|
|
1116
|
+
records.append(DependencyRecord(
|
|
1117
|
+
name=f"{group_id}:{artifact_id}",
|
|
1118
|
+
ecosystem="java",
|
|
1119
|
+
scope="dev" if scope_kw in _DEV else "direct",
|
|
1120
|
+
declared_version=version,
|
|
1121
|
+
source="manifest",
|
|
1122
|
+
manifest_path=manifest_path,
|
|
1123
|
+
))
|
|
1124
|
+
|
|
1125
|
+
return self._dedupe(records)
|
|
1126
|
+
|
|
972
1127
|
def _load_yaml_file(self, path: Path) -> Optional[dict[str, Any]]:
|
|
973
1128
|
if not path.exists():
|
|
974
1129
|
return None
|
|
@@ -54,27 +54,31 @@ def to_yaml(sm: SourceMap) -> str:
|
|
|
54
54
|
return stream.getvalue()
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def compact_view(sm: SourceMap) -> dict[str, Any]:
|
|
57
|
+
def compact_view(sm: SourceMap, *, no_tree: bool = False) -> dict[str, Any]:
|
|
58
58
|
"""Proyeccion compacta del SourceMap (~500-700 tokens).
|
|
59
59
|
|
|
60
60
|
Incluye: schema_version, project_type, stacks, entry_points,
|
|
61
61
|
project_summary (siempre), architecture_summary (siempre),
|
|
62
|
-
dependency_summary (cuando requested=True),
|
|
63
|
-
file_tree_depth1 (
|
|
62
|
+
dependency_summary + key_dependencies (cuando requested=True),
|
|
63
|
+
file_tree_depth1 (omitido si no_tree=True).
|
|
64
64
|
|
|
65
65
|
Excluye: dependencies (lista larga), docs, module_graph.
|
|
66
66
|
"""
|
|
67
|
-
depth1: dict[str, Any] =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
depth1: dict[str, Any] | None = None
|
|
68
|
+
if not no_tree:
|
|
69
|
+
depth1 = {}
|
|
70
|
+
for name, value in sm.file_tree.items():
|
|
71
|
+
if isinstance(value, dict):
|
|
72
|
+
depth1[name] = {}
|
|
73
|
+
else:
|
|
74
|
+
depth1[name] = None
|
|
73
75
|
|
|
74
76
|
dep_summary_dict: Any = None
|
|
77
|
+
key_deps: Any = None
|
|
75
78
|
if sm.dependency_summary is not None and sm.dependency_summary.requested:
|
|
76
79
|
dep_summary_dict = asdict(sm.dependency_summary)
|
|
77
80
|
dep_summary_dict.pop("dependencies", None)
|
|
81
|
+
key_deps = [asdict(d) for d in sm.key_dependencies]
|
|
78
82
|
|
|
79
83
|
env_summary_dict: Any = None
|
|
80
84
|
if sm.env_summary is not None and sm.env_summary.requested:
|
|
@@ -84,18 +88,21 @@ def compact_view(sm: SourceMap) -> dict[str, Any]:
|
|
|
84
88
|
if sm.code_notes_summary is not None and sm.code_notes_summary.requested:
|
|
85
89
|
code_notes_summary_dict = asdict(sm.code_notes_summary)
|
|
86
90
|
|
|
87
|
-
|
|
91
|
+
result: dict[str, Any] = {
|
|
88
92
|
"schema_version": sm.metadata.schema_version,
|
|
89
93
|
"project_type": sm.project_type,
|
|
90
94
|
"project_summary": sm.project_summary,
|
|
91
95
|
"architecture_summary": sm.architecture_summary,
|
|
92
96
|
"stacks": [asdict(stack) for stack in sm.stacks],
|
|
93
97
|
"entry_points": [asdict(entry_point) for entry_point in sm.entry_points],
|
|
94
|
-
"file_tree_depth1": depth1,
|
|
95
98
|
"dependency_summary": dep_summary_dict,
|
|
99
|
+
"key_dependencies": key_deps,
|
|
96
100
|
"env_summary": env_summary_dict,
|
|
97
101
|
"code_notes_summary": code_notes_summary_dict,
|
|
98
102
|
}
|
|
103
|
+
if not no_tree:
|
|
104
|
+
result["file_tree_depth1"] = depth1
|
|
105
|
+
return result
|
|
99
106
|
|
|
100
107
|
|
|
101
108
|
def normalize_source_map(sm: SourceMap) -> SourceMap:
|
|
@@ -99,13 +99,13 @@ version = "0.38.6"
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
def test_python_requirements_without_lockfile_keeps_declared_versions(tmp_path: Path) -> None:
|
|
102
|
-
(tmp_path / "requirements.txt").write_text("typer==0.
|
|
102
|
+
(tmp_path / "requirements.txt").write_text("typer==0.20.0\nrich>=13.0\n")
|
|
103
103
|
|
|
104
104
|
records, summary = DependencyAnalyzer().analyze(tmp_path)
|
|
105
105
|
|
|
106
106
|
assert summary.direct_count == 2
|
|
107
107
|
typer_dep = next(record for record in records if record.name == "typer")
|
|
108
108
|
rich_dep = next(record for record in records if record.name == "rich")
|
|
109
|
-
assert typer_dep.declared_version == "==0.
|
|
109
|
+
assert typer_dep.declared_version == "==0.20.0"
|
|
110
110
|
assert typer_dep.resolved_version is None
|
|
111
111
|
assert rich_dep.declared_version == ">=13.0"
|
|
@@ -34,7 +34,7 @@ def test_cli_dependencies_flag_enables_dependency_block(tmp_path: Path) -> None:
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def test_cli_without_dependencies_flag_keeps_block_disabled(tmp_path: Path) -> None:
|
|
37
|
-
(tmp_path / "requirements.txt").write_text("typer==0.
|
|
37
|
+
(tmp_path / "requirements.txt").write_text("typer==0.20.0\n")
|
|
38
38
|
|
|
39
39
|
result = runner.invoke(app, [str(tmp_path)])
|
|
40
40
|
|
|
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
|
{sourcecode-0.19.0 → sourcecode-0.20.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml
RENAMED
|
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
|