codeanalyzer-python 0.1.9__tar.gz → 0.1.11__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.
- codeanalyzer_python-0.1.9/README.md → codeanalyzer_python-0.1.11/PKG-INFO +58 -17
- codeanalyzer_python-0.1.9/PKG-INFO → codeanalyzer_python-0.1.11/README.md +25 -36
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/__main__.py +42 -15
- codeanalyzer_python-0.1.11/codeanalyzer/core.py +599 -0
- codeanalyzer_python-0.1.11/codeanalyzer/schema/__init__.py +72 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/schema/py_schema.py +12 -3
- codeanalyzer_python-0.1.11/codeanalyzer/syntactic_analysis/__init__.py +16 -0
- codeanalyzer_python-0.1.11/codeanalyzer/syntactic_analysis/exceptions.py +15 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/syntactic_analysis/symbol_table_builder.py +104 -167
- codeanalyzer_python-0.1.11/pyproject.toml +115 -0
- codeanalyzer_python-0.1.11/test/fixtures/whole_applications/xarray/LICENSE +191 -0
- codeanalyzer_python-0.1.11/test/fixtures/whole_applications/xarray/README.md +138 -0
- codeanalyzer_python-0.1.11/test/fixtures/whole_applications/xarray/properties/README.md +22 -0
- codeanalyzer_python-0.1.11/test/fixtures/whole_applications/xarray/xarray/datatree_/LICENSE +201 -0
- codeanalyzer_python-0.1.11/test/fixtures/whole_applications/xarray/xarray/datatree_/README.md +95 -0
- codeanalyzer_python-0.1.11/test/fixtures/whole_applications/xarray/xarray/datatree_/docs/README.md +14 -0
- codeanalyzer_python-0.1.9/codeanalyzer/core.py +0 -314
- codeanalyzer_python-0.1.9/codeanalyzer/schema/__init__.py +0 -23
- codeanalyzer_python-0.1.9/codeanalyzer/syntactic_analysis/__init__.py +0 -0
- codeanalyzer_python-0.1.9/pyproject.toml +0 -89
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/.gitignore +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/LICENSE +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/NOTICE +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/__init__.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/config/__init__.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/config/config.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/jedi/__init__.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/jedi/jedi.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/py.typed +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/semantic_analysis/__init__.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/semantic_analysis/codeql/__init__.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/semantic_analysis/codeql/codeql_analysis.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/semantic_analysis/codeql/codeql_exceptions.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/semantic_analysis/codeql/codeql_loader.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/semantic_analysis/codeql/codeql_query_runner.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/semantic_analysis/wala/__init__.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/utils/__init__.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/utils/logging.py +0 -0
- {codeanalyzer_python-0.1.9 → codeanalyzer_python-0.1.11}/codeanalyzer/utils/progress_bar.py +0 -0
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codeanalyzer-python
|
|
3
|
+
Version: 0.1.11
|
|
4
|
+
Summary: Static Analysis on Python source code using Jedi, CodeQL and Treesitter.
|
|
5
|
+
Author-email: Rahul Krishna <i.m.ralk@gmail.com>
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
License-File: NOTICE
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Requires-Dist: jedi<0.20.0,>=0.18.0; python_version < '3.11'
|
|
10
|
+
Requires-Dist: jedi<=0.19.2; python_version >= '3.11'
|
|
11
|
+
Requires-Dist: msgpack<1.0.7,>=1.0.0; python_version < '3.11'
|
|
12
|
+
Requires-Dist: msgpack<2.0.0,>=1.0.7; python_version >= '3.11'
|
|
13
|
+
Requires-Dist: networkx<3.2.0,>=2.6.0; python_version < '3.11'
|
|
14
|
+
Requires-Dist: networkx<4.0.0,>=3.0.0; python_version >= '3.11'
|
|
15
|
+
Requires-Dist: numpy<1.24.0,>=1.21.0; python_version < '3.11'
|
|
16
|
+
Requires-Dist: numpy<2.0.0,>=1.24.0; python_version >= '3.11' and python_version < '3.12'
|
|
17
|
+
Requires-Dist: numpy<2.0.0,>=1.26.0; python_version >= '3.12'
|
|
18
|
+
Requires-Dist: packaging>=25.0
|
|
19
|
+
Requires-Dist: pandas<2.0.0,>=1.3.0; python_version < '3.11'
|
|
20
|
+
Requires-Dist: pandas<3.0.0,>=2.0.0; python_version >= '3.11'
|
|
21
|
+
Requires-Dist: pydantic<2.0.0,>=1.8.0; python_version < '3.11'
|
|
22
|
+
Requires-Dist: pydantic<3.0.0,>=2.0.0; python_version >= '3.11'
|
|
23
|
+
Requires-Dist: ray<3.0.0,>=2.10.0; python_version >= '3.11'
|
|
24
|
+
Requires-Dist: ray==2.0.0; python_version < '3.11'
|
|
25
|
+
Requires-Dist: requests<3.0.0,>=2.20.0; python_version >= '3.11'
|
|
26
|
+
Requires-Dist: rich<14.0.0,>=12.6.0; python_version < '3.11'
|
|
27
|
+
Requires-Dist: rich<15.0.0,>=14.0.0; python_version >= '3.11'
|
|
28
|
+
Requires-Dist: typer<1.0.0,>=0.9.0; python_version < '3.11'
|
|
29
|
+
Requires-Dist: typer<2.0.0,>=0.9.0; python_version >= '3.11'
|
|
30
|
+
Requires-Dist: typing-extensions<5.0.0,>=4.0.0; python_version < '3.11'
|
|
31
|
+
Requires-Dist: typing-extensions<6.0.0,>=4.5.0; python_version >= '3.11'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
1
34
|

|
|
2
35
|
|
|
3
36
|
# A Python Static Analysis Toolkit (and Library)
|
|
@@ -76,17 +109,18 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
76
109
|
Static Analysis on Python source code using Jedi, CodeQL and Tree sitter.
|
|
77
110
|
|
|
78
111
|
|
|
79
|
-
╭─ Options
|
|
80
|
-
│ * --input -i PATH
|
|
81
|
-
│ --output -o PATH
|
|
82
|
-
│ --
|
|
83
|
-
│ --
|
|
84
|
-
│ --
|
|
85
|
-
│ --
|
|
86
|
-
│ --
|
|
87
|
-
│
|
|
88
|
-
│
|
|
89
|
-
|
|
112
|
+
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
113
|
+
│ * --input -i PATH Path to the project root directory. [default: None] [required] │
|
|
114
|
+
│ --output -o PATH Output directory for artifacts. [default: None] │
|
|
115
|
+
│ --format -f [json|msgpack] Output format: json or msgpack. [default: json] │
|
|
116
|
+
│ --analysis-level -a INTEGER 1: symbol table, 2: call graph. [default: 1] │
|
|
117
|
+
│ --codeql --no-codeql Enable CodeQL-based analysis. [default: no-codeql] │
|
|
118
|
+
│ --eager --lazy Enable eager or lazy analysis. Defaults to lazy. [default: lazy] │
|
|
119
|
+
│ --cache-dir -c PATH Directory to store analysis cache. [default: None] │
|
|
120
|
+
│ --clear-cache --keep-cache Clear cache after analysis. [default: clear-cache] │
|
|
121
|
+
│ -v INTEGER Increase verbosity: -v, -vv, -vvv [default: 0] │
|
|
122
|
+
│ --help Show this message and exit. │
|
|
123
|
+
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
90
124
|
```
|
|
91
125
|
|
|
92
126
|
### Examples
|
|
@@ -104,7 +138,14 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
104
138
|
|
|
105
139
|
Now, you can find the analysis results in `analysis.json` in the specified directory.
|
|
106
140
|
|
|
107
|
-
2. **
|
|
141
|
+
2. **Change output format to msgpack:**
|
|
142
|
+
```bash
|
|
143
|
+
codeanalyzer --input ./my-python-project --output /path/to/analysis-results --format msgpack
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This will save the analysis results in `analysis.msgpack` in the specified directory.
|
|
147
|
+
|
|
148
|
+
3. **Toggle analysis levels with `--analysis-level`:**
|
|
108
149
|
```bash
|
|
109
150
|
codeanalyzer --input ./my-python-project --analysis-level 1 # Symbol table only
|
|
110
151
|
```
|
|
@@ -114,7 +155,7 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
114
155
|
```
|
|
115
156
|
***Note: The `--analysis-level=2` is not yet implemented in this version.***
|
|
116
157
|
|
|
117
|
-
|
|
158
|
+
4. **Analysis with CodeQL enabled:**
|
|
118
159
|
```bash
|
|
119
160
|
codeanalyzer --input ./my-python-project --codeql
|
|
120
161
|
```
|
|
@@ -122,7 +163,7 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
122
163
|
|
|
123
164
|
***Note: Not yet fully implemented. Please refrain from using this option until further notice.***
|
|
124
165
|
|
|
125
|
-
|
|
166
|
+
5. **Eager analysis with custom cache directory:**
|
|
126
167
|
```bash
|
|
127
168
|
codeanalyzer --input ./my-python-project --eager --cache-dir /path/to/custom-cache
|
|
128
169
|
```
|
|
@@ -130,14 +171,14 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
130
171
|
|
|
131
172
|
If you provide --cache-dir, the cache will be stored in that directory. If not specified, it defaults to `.codeanalyzer` in the current working directory (`$PWD`).
|
|
132
173
|
|
|
133
|
-
|
|
174
|
+
6. **Quiet mode (minimal output):**
|
|
134
175
|
```bash
|
|
135
176
|
codeanalyzer --input /path/to/my-python-project --quiet
|
|
136
177
|
```
|
|
137
178
|
|
|
138
|
-
|
|
179
|
+
## Output
|
|
139
180
|
|
|
140
|
-
By default, analysis results are printed to stdout in JSON format. When using the `--output` option, results are saved to `analysis.json` in the specified directory.
|
|
181
|
+
By default, analysis results are printed to stdout in JSON format. When using the `--output` option, results are saved to `analysis.json` in the specified directory. If you use the `--format=msgpack` option, the results will be saved in `analysis.msgpack`, which is a binary format that can be more efficient for storage and transmission.
|
|
141
182
|
|
|
142
183
|
## Development
|
|
143
184
|
|
|
@@ -1,22 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: codeanalyzer-python
|
|
3
|
-
Version: 0.1.9
|
|
4
|
-
Summary: Static Analysis on Python source code using Jedi, CodeQL and Treesitter.
|
|
5
|
-
Author-email: Rahul Krishna <i.m.ralk@gmail.com>
|
|
6
|
-
License-File: LICENSE
|
|
7
|
-
License-File: NOTICE
|
|
8
|
-
Requires-Python: >=3.10
|
|
9
|
-
Requires-Dist: jedi>=0.19.2
|
|
10
|
-
Requires-Dist: loguru>=0.7.3
|
|
11
|
-
Requires-Dist: msgpack>=1.1.1
|
|
12
|
-
Requires-Dist: networkx>=3.4.2
|
|
13
|
-
Requires-Dist: pandas>=2.3.1
|
|
14
|
-
Requires-Dist: pydantic>=2.11.7
|
|
15
|
-
Requires-Dist: requests>=2.32.4
|
|
16
|
-
Requires-Dist: rich>=14.0.0
|
|
17
|
-
Requires-Dist: typer>=0.16.0
|
|
18
|
-
Description-Content-Type: text/markdown
|
|
19
|
-
|
|
20
1
|

|
|
21
2
|
|
|
22
3
|
# A Python Static Analysis Toolkit (and Library)
|
|
@@ -95,17 +76,18 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
95
76
|
Static Analysis on Python source code using Jedi, CodeQL and Tree sitter.
|
|
96
77
|
|
|
97
78
|
|
|
98
|
-
╭─ Options
|
|
99
|
-
│ * --input -i PATH
|
|
100
|
-
│ --output -o PATH
|
|
101
|
-
│ --
|
|
102
|
-
│ --
|
|
103
|
-
│ --
|
|
104
|
-
│ --
|
|
105
|
-
│ --
|
|
106
|
-
│
|
|
107
|
-
│
|
|
108
|
-
|
|
79
|
+
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
80
|
+
│ * --input -i PATH Path to the project root directory. [default: None] [required] │
|
|
81
|
+
│ --output -o PATH Output directory for artifacts. [default: None] │
|
|
82
|
+
│ --format -f [json|msgpack] Output format: json or msgpack. [default: json] │
|
|
83
|
+
│ --analysis-level -a INTEGER 1: symbol table, 2: call graph. [default: 1] │
|
|
84
|
+
│ --codeql --no-codeql Enable CodeQL-based analysis. [default: no-codeql] │
|
|
85
|
+
│ --eager --lazy Enable eager or lazy analysis. Defaults to lazy. [default: lazy] │
|
|
86
|
+
│ --cache-dir -c PATH Directory to store analysis cache. [default: None] │
|
|
87
|
+
│ --clear-cache --keep-cache Clear cache after analysis. [default: clear-cache] │
|
|
88
|
+
│ -v INTEGER Increase verbosity: -v, -vv, -vvv [default: 0] │
|
|
89
|
+
│ --help Show this message and exit. │
|
|
90
|
+
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
109
91
|
```
|
|
110
92
|
|
|
111
93
|
### Examples
|
|
@@ -123,7 +105,14 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
123
105
|
|
|
124
106
|
Now, you can find the analysis results in `analysis.json` in the specified directory.
|
|
125
107
|
|
|
126
|
-
2. **
|
|
108
|
+
2. **Change output format to msgpack:**
|
|
109
|
+
```bash
|
|
110
|
+
codeanalyzer --input ./my-python-project --output /path/to/analysis-results --format msgpack
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This will save the analysis results in `analysis.msgpack` in the specified directory.
|
|
114
|
+
|
|
115
|
+
3. **Toggle analysis levels with `--analysis-level`:**
|
|
127
116
|
```bash
|
|
128
117
|
codeanalyzer --input ./my-python-project --analysis-level 1 # Symbol table only
|
|
129
118
|
```
|
|
@@ -133,7 +122,7 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
133
122
|
```
|
|
134
123
|
***Note: The `--analysis-level=2` is not yet implemented in this version.***
|
|
135
124
|
|
|
136
|
-
|
|
125
|
+
4. **Analysis with CodeQL enabled:**
|
|
137
126
|
```bash
|
|
138
127
|
codeanalyzer --input ./my-python-project --codeql
|
|
139
128
|
```
|
|
@@ -141,7 +130,7 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
141
130
|
|
|
142
131
|
***Note: Not yet fully implemented. Please refrain from using this option until further notice.***
|
|
143
132
|
|
|
144
|
-
|
|
133
|
+
5. **Eager analysis with custom cache directory:**
|
|
145
134
|
```bash
|
|
146
135
|
codeanalyzer --input ./my-python-project --eager --cache-dir /path/to/custom-cache
|
|
147
136
|
```
|
|
@@ -149,14 +138,14 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
|
|
|
149
138
|
|
|
150
139
|
If you provide --cache-dir, the cache will be stored in that directory. If not specified, it defaults to `.codeanalyzer` in the current working directory (`$PWD`).
|
|
151
140
|
|
|
152
|
-
|
|
141
|
+
6. **Quiet mode (minimal output):**
|
|
153
142
|
```bash
|
|
154
143
|
codeanalyzer --input /path/to/my-python-project --quiet
|
|
155
144
|
```
|
|
156
145
|
|
|
157
|
-
|
|
146
|
+
## Output
|
|
158
147
|
|
|
159
|
-
By default, analysis results are printed to stdout in JSON format. When using the `--output` option, results are saved to `analysis.json` in the specified directory.
|
|
148
|
+
By default, analysis results are printed to stdout in JSON format. When using the `--output` option, results are saved to `analysis.json` in the specified directory. If you use the `--format=msgpack` option, the results will be saved in `analysis.msgpack`, which is a binary format that can be more efficient for storage and transmission.
|
|
160
149
|
|
|
161
150
|
## Development
|
|
162
151
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Optional, Annotated
|
|
3
3
|
|
|
4
4
|
import typer
|
|
5
5
|
|
|
6
6
|
from codeanalyzer.core import Codeanalyzer
|
|
7
7
|
from codeanalyzer.utils import _set_log_level, logger
|
|
8
8
|
from codeanalyzer.config import OutputFormat
|
|
9
|
-
|
|
9
|
+
from codeanalyzer.schema import model_dump_json
|
|
10
10
|
|
|
11
11
|
def main(
|
|
12
12
|
input: Annotated[
|
|
@@ -32,6 +32,12 @@ def main(
|
|
|
32
32
|
using_codeql: Annotated[
|
|
33
33
|
bool, typer.Option("--codeql/--no-codeql", help="Enable CodeQL-based analysis.")
|
|
34
34
|
] = False,
|
|
35
|
+
using_ray: Annotated[
|
|
36
|
+
bool,
|
|
37
|
+
typer.Option(
|
|
38
|
+
"--ray/--no-ray", help="Enable Ray for distributed analysis."
|
|
39
|
+
),
|
|
40
|
+
] = False,
|
|
35
41
|
rebuild_analysis: Annotated[
|
|
36
42
|
bool,
|
|
37
43
|
typer.Option(
|
|
@@ -39,18 +45,32 @@ def main(
|
|
|
39
45
|
help="Enable eager or lazy analysis. Defaults to lazy.",
|
|
40
46
|
),
|
|
41
47
|
] = False,
|
|
48
|
+
skip_tests: Annotated[
|
|
49
|
+
bool,
|
|
50
|
+
typer.Option(
|
|
51
|
+
"--skip-tests/--include-tests",
|
|
52
|
+
help="Skip test files in analysis.",
|
|
53
|
+
),
|
|
54
|
+
] = True,
|
|
55
|
+
file_name: Annotated[
|
|
56
|
+
Optional[Path],
|
|
57
|
+
typer.Option(
|
|
58
|
+
"--file-name",
|
|
59
|
+
help="Analyze only the specified file (relative to input directory).",
|
|
60
|
+
),
|
|
61
|
+
] = None,
|
|
42
62
|
cache_dir: Annotated[
|
|
43
63
|
Optional[Path],
|
|
44
64
|
typer.Option(
|
|
45
65
|
"-c",
|
|
46
66
|
"--cache-dir",
|
|
47
|
-
help="Directory to store analysis cache.",
|
|
67
|
+
help="Directory to store analysis cache. Defaults to '.codeanalyzer' in the input directory.",
|
|
48
68
|
),
|
|
49
69
|
] = None,
|
|
50
70
|
clear_cache: Annotated[
|
|
51
71
|
bool,
|
|
52
|
-
typer.Option("--clear-cache/--keep-cache", help="Clear cache after analysis."),
|
|
53
|
-
] =
|
|
72
|
+
typer.Option("--clear-cache/--keep-cache", help="Clear cache after analysis. By default, cache is retained."),
|
|
73
|
+
] = False,
|
|
54
74
|
verbosity: Annotated[
|
|
55
75
|
int, typer.Option("-v", count=True, help="Increase verbosity: -v, -vv, -vvv")
|
|
56
76
|
] = 0,
|
|
@@ -62,21 +82,28 @@ def main(
|
|
|
62
82
|
logger.error(f"Input path '{input}' does not exist.")
|
|
63
83
|
raise typer.Exit(code=1)
|
|
64
84
|
|
|
85
|
+
# Validate file_name if provided
|
|
86
|
+
if file_name is not None:
|
|
87
|
+
full_file_path = input / file_name
|
|
88
|
+
if not full_file_path.exists():
|
|
89
|
+
logger.error(f"Specified file '{file_name}' does not exist in '{input}'.")
|
|
90
|
+
raise typer.Exit(code=1)
|
|
91
|
+
if not full_file_path.is_file():
|
|
92
|
+
logger.error(f"Specified path '{file_name}' is not a file.")
|
|
93
|
+
raise typer.Exit(code=1)
|
|
94
|
+
if not str(file_name).endswith('.py'):
|
|
95
|
+
logger.error(f"Specified file '{file_name}' is not a Python file (.py).")
|
|
96
|
+
raise typer.Exit(code=1)
|
|
97
|
+
|
|
65
98
|
with Codeanalyzer(
|
|
66
|
-
input, analysis_level, using_codeql, rebuild_analysis, cache_dir, clear_cache
|
|
99
|
+
input, analysis_level, skip_tests, using_codeql, rebuild_analysis, cache_dir, clear_cache, using_ray, file_name
|
|
67
100
|
) as analyzer:
|
|
68
101
|
artifacts = analyzer.analyze()
|
|
69
102
|
|
|
70
103
|
# Handle output based on format
|
|
71
104
|
if output is None:
|
|
72
105
|
# Output to stdout (only for JSON)
|
|
73
|
-
|
|
74
|
-
print(artifacts.model_dump_json(separators=(",", ":")))
|
|
75
|
-
else:
|
|
76
|
-
logger.error(
|
|
77
|
-
f"Format '{format.value}' requires an output directory (use -o/--output)"
|
|
78
|
-
)
|
|
79
|
-
raise typer.Exit(code=1)
|
|
106
|
+
print(model_dump_json(artifacts, separators=(",", ":")))
|
|
80
107
|
else:
|
|
81
108
|
# Output to file
|
|
82
109
|
output.mkdir(parents=True, exist_ok=True)
|
|
@@ -87,8 +114,8 @@ def _write_output(artifacts, output_dir: Path, format: OutputFormat):
|
|
|
87
114
|
"""Write artifacts to file in the specified format."""
|
|
88
115
|
if format == OutputFormat.JSON:
|
|
89
116
|
output_file = output_dir / "analysis.json"
|
|
90
|
-
# Use Pydantic's
|
|
91
|
-
json_str =
|
|
117
|
+
# Use Pydantic's model_dump_json() for compact output
|
|
118
|
+
json_str = model_dump_json(artifacts, indent=None)
|
|
92
119
|
with output_file.open("w") as f:
|
|
93
120
|
f.write(json_str)
|
|
94
121
|
logger.info(f"Analysis saved to {output_file}")
|