project-doctor 0.6.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.
- project_doctor-0.6.0/CHANGELOG.md +9 -0
- project_doctor-0.6.0/LICENSE +21 -0
- project_doctor-0.6.0/MANIFEST.in +7 -0
- project_doctor-0.6.0/PKG-INFO +398 -0
- project_doctor-0.6.0/README.md +362 -0
- project_doctor-0.6.0/docs/PYPI_RELEASE.md +51 -0
- project_doctor-0.6.0/examples/sample_project/app.py +21 -0
- project_doctor-0.6.0/examples/sample_project/pyproject.toml +9 -0
- project_doctor-0.6.0/examples/sample_project/uv.lock +17 -0
- project_doctor-0.6.0/examples/sample_project/worker.py +4 -0
- project_doctor-0.6.0/pyproject.toml +73 -0
- project_doctor-0.6.0/scripts/benchmark.py +118 -0
- project_doctor-0.6.0/setup.cfg +4 -0
- project_doctor-0.6.0/src/project_doctor/__init__.py +34 -0
- project_doctor-0.6.0/src/project_doctor/__main__.py +4 -0
- project_doctor-0.6.0/src/project_doctor/analyze.py +171 -0
- project_doctor-0.6.0/src/project_doctor/cli.py +381 -0
- project_doctor-0.6.0/src/project_doctor/context.py +25 -0
- project_doctor-0.6.0/src/project_doctor/dependencies.py +360 -0
- project_doctor-0.6.0/src/project_doctor/entrypoint.py +85 -0
- project_doctor-0.6.0/src/project_doctor/import_timing.py +150 -0
- project_doctor-0.6.0/src/project_doctor/models.py +126 -0
- project_doctor-0.6.0/src/project_doctor/py.typed +1 -0
- project_doctor-0.6.0/src/project_doctor/report.py +344 -0
- project_doctor-0.6.0/src/project_doctor/static_scan.py +301 -0
- project_doctor-0.6.0/src/project_doctor/utils.py +98 -0
- project_doctor-0.6.0/src/project_doctor/uv.py +103 -0
- project_doctor-0.6.0/src/project_doctor.egg-info/PKG-INFO +398 -0
- project_doctor-0.6.0/src/project_doctor.egg-info/SOURCES.txt +35 -0
- project_doctor-0.6.0/src/project_doctor.egg-info/dependency_links.txt +1 -0
- project_doctor-0.6.0/src/project_doctor.egg-info/entry_points.txt +2 -0
- project_doctor-0.6.0/src/project_doctor.egg-info/requires.txt +12 -0
- project_doctor-0.6.0/src/project_doctor.egg-info/top_level.txt +1 -0
- project_doctor-0.6.0/tests/test_basic.py +111 -0
- project_doctor-0.6.0/tests/test_performance_features.py +173 -0
- project_doctor-0.6.0/tests/test_release_branding.py +69 -0
- project_doctor-0.6.0/tests/test_wow_entrypoint_uv.py +285 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
- Renamed the project to Project Doctor with the `project-doctor` distribution and CLI.
|
|
6
|
+
- Moved the import package to `project_doctor`.
|
|
7
|
+
- Updated README branding, install examples, CI snippets, badges, and development commands.
|
|
8
|
+
- Added release documentation for building, checking, and publishing PyPI artifacts without storing credentials in the repository.
|
|
9
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Project Doctor maintainers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: project-doctor
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: A local-first health checker for Python imports, dependencies, startup time, and package bloat.
|
|
5
|
+
Author: Project Doctor maintainers
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/billjamesevans/project-doctor
|
|
8
|
+
Project-URL: Repository, https://github.com/billjamesevans/project-doctor
|
|
9
|
+
Project-URL: Issues, https://github.com/billjamesevans/project-doctor/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/billjamesevans/project-doctor/releases
|
|
11
|
+
Keywords: python,performance,imports,dependencies,optimizer,cli
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
21
|
+
Classifier: Topic :: System :: Software Distribution
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: bandit>=1.9; extra == "dev"
|
|
27
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy>=2.1; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest>=9; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.14; extra == "dev"
|
|
31
|
+
Requires-Dist: twine>=6; extra == "dev"
|
|
32
|
+
Provides-Extra: security
|
|
33
|
+
Requires-Dist: detect-secrets>=1.5; extra == "security"
|
|
34
|
+
Requires-Dist: pip-audit>=2.10; extra == "security"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# Project Doctor
|
|
38
|
+
|
|
39
|
+
[](https://github.com/billjamesevans/project-doctor/actions/workflows/ci.yml)
|
|
40
|
+
[](https://www.python.org/downloads/)
|
|
41
|
+
[](LICENSE)
|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
A local-first health checker for Python imports, dependencies, startup time, and package bloat.
|
|
45
|
+
|
|
46
|
+
Project Doctor is a zero-dependency analyzer for finding project optimization work that usually hides in plain sight:
|
|
47
|
+
|
|
48
|
+
- entrypoint startup drag
|
|
49
|
+
- slow third-party imports
|
|
50
|
+
- likely unused dependencies
|
|
51
|
+
- possible undeclared imports
|
|
52
|
+
- opt-in large installed package checks
|
|
53
|
+
- top-level imports that look safe to move into deferred code paths
|
|
54
|
+
- CI thresholds for dependency and import hygiene
|
|
55
|
+
- uv.lock sync status and package explanations
|
|
56
|
+
|
|
57
|
+
Project Doctor never edits your code. It produces reviewable reports and CI-friendly checks so teams can make deliberate changes.
|
|
58
|
+
|
|
59
|
+
## Security and privacy
|
|
60
|
+
|
|
61
|
+
Project Doctor is local-first and safe by default. Static scans parse source files with Python's `ast` module and do not import your project code. Optional import timing must be enabled with `--import-time`; it imports third-party modules in child processes, so leave it off when reviewing sensitive projects or code with import-time side effects. Installed package size checks are also opt-in with `--package-sizes` because they walk installed distribution metadata.
|
|
62
|
+
|
|
63
|
+
## Install
|
|
64
|
+
|
|
65
|
+
Current reliable install path:
|
|
66
|
+
|
|
67
|
+
From this folder:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
python3 -m pip install -e .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then run:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
project-doctor analyze /path/to/your/project
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Or without installing:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
PYTHONPATH=src python3 -m project_doctor analyze /path/to/your/project
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
After the PyPI release is live:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install project-doctor
|
|
89
|
+
uv tool install project-doctor
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Quick examples
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
project-doctor doctor
|
|
96
|
+
project-doctor analyze examples/sample_project
|
|
97
|
+
project-doctor analyze examples/sample_project --json -o project-doctor-report.json
|
|
98
|
+
project-doctor analyze examples/sample_project --jobs auto --package-sizes
|
|
99
|
+
project-doctor analyze examples/sample_project --entrypoint "python app.py"
|
|
100
|
+
project-doctor analyze examples/sample_project --uv
|
|
101
|
+
project-doctor check examples/sample_project --max-unused 0
|
|
102
|
+
project-doctor check examples/sample_project --import-time --json --max-import-ms 150
|
|
103
|
+
project-doctor sync-check examples/sample_project/uv.lock
|
|
104
|
+
project-doctor explain-package pandas examples/sample_project --uv
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`analyze` writes a shareable "wow" report by default. Use `--report detailed` for the longer audit report. `check` prints a compact status report and exits nonzero when a configured threshold is exceeded.
|
|
108
|
+
|
|
109
|
+
## Example report
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
Project Doctor Report
|
|
113
|
+
|
|
114
|
+
Startup time: 1.42s
|
|
115
|
+
Potential avoidable import cost: 630ms
|
|
116
|
+
|
|
117
|
+
Top startup contributors:
|
|
118
|
+
- pandas: 312ms
|
|
119
|
+
- boto3: 205ms
|
|
120
|
+
- matplotlib: 113ms
|
|
121
|
+
|
|
122
|
+
Likely unused dependencies:
|
|
123
|
+
- openpyxl
|
|
124
|
+
- beautifulsoup4
|
|
125
|
+
- python-dotenv
|
|
126
|
+
|
|
127
|
+
Possible undeclared imports:
|
|
128
|
+
- requests imported but not declared
|
|
129
|
+
|
|
130
|
+
Largest installed packages:
|
|
131
|
+
- torch: 742MB
|
|
132
|
+
- pandas: 78MB
|
|
133
|
+
- botocore: 71MB
|
|
134
|
+
|
|
135
|
+
Suggested quick wins:
|
|
136
|
+
1. Move `pandas` import at `reports.py:3` inside the deferred function that uses it.
|
|
137
|
+
2. Remove `openpyxl` if it is no longer used by active code paths.
|
|
138
|
+
3. Add `requests` to `pyproject.toml`.
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Python API
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from project_doctor import AnalysisContext, analyze_project
|
|
145
|
+
|
|
146
|
+
context = AnalysisContext.from_environment()
|
|
147
|
+
report = analyze_project(
|
|
148
|
+
"examples/sample_project",
|
|
149
|
+
context=context,
|
|
150
|
+
jobs="auto",
|
|
151
|
+
run_import_timing=False,
|
|
152
|
+
collect_package_sizes=False,
|
|
153
|
+
entrypoint="python app.py",
|
|
154
|
+
)
|
|
155
|
+
print(report.unused_dependencies)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The returned `AnalysisReport` and nested report objects are dataclasses and can be converted to dictionaries with `report.to_dict()`. Reuse `AnalysisContext` when analyzing multiple projects in one process; it keeps installed package metadata and package size estimates cached.
|
|
159
|
+
|
|
160
|
+
## What Project Doctor checks
|
|
161
|
+
|
|
162
|
+
### Static import scan
|
|
163
|
+
|
|
164
|
+
Project Doctor parses Python source with `ast`, so it can read imports without importing your project code. Syntax errors are reported as warnings instead of aborting the full scan.
|
|
165
|
+
|
|
166
|
+
### Dependency usage
|
|
167
|
+
|
|
168
|
+
Project Doctor reads dependencies from:
|
|
169
|
+
|
|
170
|
+
- `pyproject.toml` `[project.dependencies]`
|
|
171
|
+
- `pyproject.toml` `[project.optional-dependencies]`
|
|
172
|
+
- `pyproject.toml` `[dependency-groups]`, including `{ include-group = "..." }`
|
|
173
|
+
- common Poetry dependency sections
|
|
174
|
+
- `requirements*.txt`, including nested `-r` and `--requirement` includes
|
|
175
|
+
|
|
176
|
+
It compares declared dependencies against static imports. Results marked `unused` should be treated as a review queue, not an automatic delete list.
|
|
177
|
+
|
|
178
|
+
### Import timings
|
|
179
|
+
|
|
180
|
+
When `--import-time` is enabled, Project Doctor runs a subprocess like this for each likely third-party top-level import:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
python -X importtime -c "import pandas"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
This keeps imports out of the analyzer process, but the imported library can still run import-time side effects in the child process. Leave import timing disabled when you want a purely static scan.
|
|
187
|
+
|
|
188
|
+
### Entrypoint startup timing
|
|
189
|
+
|
|
190
|
+
Entrypoint mode measures the command users actually wait on:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
project-doctor analyze . --entrypoint "python app.py"
|
|
194
|
+
project-doctor analyze . --entrypoint "uvicorn app:app"
|
|
195
|
+
project-doctor analyze . --entrypoint "python -m my_cli"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Project Doctor runs the command with Python import profiling enabled and `shell=False`, then folds the parsed startup import costs into the report. Server-style commands may time out by design; Project Doctor still reports import data captured before the timeout.
|
|
199
|
+
|
|
200
|
+
### Lazy-import candidates
|
|
201
|
+
|
|
202
|
+
Project Doctor looks for imports that are defined at module load but only used inside deferred function or method bodies.
|
|
203
|
+
|
|
204
|
+
For example:
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
import pandas as pd
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def make_report(rows):
|
|
211
|
+
return pd.DataFrame(rows)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Project Doctor may suggest:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
def make_report(rows):
|
|
218
|
+
import pandas as pd
|
|
219
|
+
return pd.DataFrame(rows)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
That kind of change can reduce startup time for CLIs, Lambdas, Flask/FastAPI apps, and agent scripts when a heavy dependency is only needed on a less-common path.
|
|
223
|
+
|
|
224
|
+
## CLI
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
project-doctor doctor [path] [options]
|
|
228
|
+
|
|
229
|
+
Runs the default project health report. It is an alias for `project-doctor analyze .` with the same analysis options.
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
project-doctor analyze [path] [options]
|
|
234
|
+
|
|
235
|
+
Options:
|
|
236
|
+
--json Emit JSON instead of Markdown
|
|
237
|
+
--report wow|detailed Human report style, default wow
|
|
238
|
+
--output FILE, -o FILE Write report to a file
|
|
239
|
+
--import-time Run subprocess import timing checks
|
|
240
|
+
--no-import-time Skip subprocess import timing checks, default
|
|
241
|
+
--import-time-limit N Max third-party modules to time, default 20
|
|
242
|
+
--import-time-timeout SECONDS Timeout per import, default 10
|
|
243
|
+
--package-sizes Collect installed package sizes
|
|
244
|
+
--no-package-sizes Skip installed package size checks, default
|
|
245
|
+
--jobs N|auto Static scan workers, default auto
|
|
246
|
+
--entrypoint COMMAND Measure startup for a real entrypoint command
|
|
247
|
+
--entrypoint-timeout SECONDS Timeout for entrypoint measurement, default 10
|
|
248
|
+
--uv Include uv.lock status
|
|
249
|
+
--max-files N Max Python files to scan, default 5000
|
|
250
|
+
--exclude DIR Extra directory name to exclude; repeatable
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
project-doctor check [path] [options]
|
|
255
|
+
|
|
256
|
+
Options:
|
|
257
|
+
--json Emit machine-readable check results
|
|
258
|
+
--max-unused N Max likely unused dependencies, default 0
|
|
259
|
+
--max-undeclared N Max possible undeclared imports, default 0
|
|
260
|
+
--max-lazy-imports N Max lazy-import candidates
|
|
261
|
+
--max-import-ms N Max cumulative import time for any measured module
|
|
262
|
+
--max-package-mb N Max installed package size; enables package size checks
|
|
263
|
+
--import-time Run subprocess import timing checks
|
|
264
|
+
--no-import-time Skip subprocess import timing checks, default
|
|
265
|
+
--import-time-limit N Max third-party modules to time, default 20
|
|
266
|
+
--import-time-timeout SECONDS Timeout per import, default 10
|
|
267
|
+
--package-sizes Collect installed package sizes
|
|
268
|
+
--no-package-sizes Skip installed package size checks, default
|
|
269
|
+
--jobs N|auto Static scan workers, default auto
|
|
270
|
+
--entrypoint COMMAND Measure startup for a real entrypoint command
|
|
271
|
+
--entrypoint-timeout SECONDS Timeout for entrypoint measurement, default 10
|
|
272
|
+
--uv Include uv.lock status
|
|
273
|
+
--max-files N Max Python files to scan, default 5000
|
|
274
|
+
--exclude DIR Extra directory name to exclude; repeatable
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
project-doctor sync-check [uv.lock] [options]
|
|
279
|
+
|
|
280
|
+
Options:
|
|
281
|
+
--json Emit machine-readable sync results
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
project-doctor explain-package PACKAGE [path] [options]
|
|
286
|
+
|
|
287
|
+
Options:
|
|
288
|
+
--uv Include uv.lock status
|
|
289
|
+
--json Emit machine-readable package explanation
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## CI
|
|
293
|
+
|
|
294
|
+
Add Project Doctor to GitHub Actions as a dependency hygiene gate:
|
|
295
|
+
|
|
296
|
+
```yaml
|
|
297
|
+
- name: Check Python dependency health
|
|
298
|
+
run: project-doctor check . --max-unused 0 --max-undeclared 0 --max-package-mb 100
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Intended full workflow after first package release and name/package ownership confirmation:
|
|
302
|
+
|
|
303
|
+
```yaml
|
|
304
|
+
name: project-doctor
|
|
305
|
+
|
|
306
|
+
on: [push, pull_request]
|
|
307
|
+
|
|
308
|
+
jobs:
|
|
309
|
+
project-doctor:
|
|
310
|
+
runs-on: ubuntu-latest
|
|
311
|
+
steps:
|
|
312
|
+
- uses: actions/checkout@v4
|
|
313
|
+
- uses: actions/setup-python@v5
|
|
314
|
+
with:
|
|
315
|
+
python-version: "3.12"
|
|
316
|
+
- run: pip install project-doctor
|
|
317
|
+
- run: project-doctor check . --max-unused 0 --max-undeclared 0
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
For projects that use uv:
|
|
321
|
+
|
|
322
|
+
```yaml
|
|
323
|
+
- name: Check uv lock sync
|
|
324
|
+
run: project-doctor sync-check uv.lock
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Badge for project docs:
|
|
328
|
+
|
|
329
|
+
```markdown
|
|
330
|
+

|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## uv
|
|
334
|
+
|
|
335
|
+
Project Doctor understands the common `pyproject.toml` + `uv.lock` workflow:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
project-doctor analyze --uv
|
|
339
|
+
project-doctor sync-check uv.lock
|
|
340
|
+
project-doctor explain-package pandas --uv
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
`sync-check` verifies that direct dependencies declared in `pyproject.toml` are represented in `uv.lock`. `explain-package` shows whether a package is declared, which import names map to it, whether it is installed locally, and whether uv has locked it.
|
|
344
|
+
|
|
345
|
+
## Performance
|
|
346
|
+
|
|
347
|
+
Project Doctor keeps the default path fast:
|
|
348
|
+
|
|
349
|
+
- installed package metadata is indexed once per analysis context
|
|
350
|
+
- package size checks are skipped unless requested or needed by `--max-package-mb`
|
|
351
|
+
- static scans stream into aggregate results instead of retaining every file scan object
|
|
352
|
+
- `--jobs auto` uses serial scanning for small projects and bounded parallel scanning for larger projects
|
|
353
|
+
|
|
354
|
+
Run the benchmark helper against a synthetic project:
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
PYTHONPATH=src python3 scripts/benchmark.py --files 1000 --runs 5 --jobs auto
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Or benchmark a real project:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
PYTHONPATH=src python3 scripts/benchmark.py /path/to/project --runs 5 --jobs auto
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Development
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
python3 -m venv .venv
|
|
370
|
+
.venv/bin/python -m pip install -e ".[dev,security]"
|
|
371
|
+
.venv/bin/python -m pytest
|
|
372
|
+
.venv/bin/python -m ruff check .
|
|
373
|
+
.venv/bin/python -m mypy src/project_doctor tests
|
|
374
|
+
.venv/bin/python -m bandit -r src examples scripts -q
|
|
375
|
+
.venv/bin/python -m pip_audit
|
|
376
|
+
.venv/bin/python scripts/benchmark.py --files 200 --runs 2
|
|
377
|
+
.venv/bin/python -m build
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Current limitations
|
|
381
|
+
|
|
382
|
+
- Static analysis misses dynamic imports and plugin systems.
|
|
383
|
+
- Dependency names do not always match import names.
|
|
384
|
+
- Optional dependencies may be marked unused if their optional code path is not statically imported.
|
|
385
|
+
- Opt-in import timing imports third-party packages in a subprocess, which can still trigger child-process side effects.
|
|
386
|
+
- Entrypoint mode runs your command in a subprocess; use it for commands that are safe to execute locally.
|
|
387
|
+
- Package size checks are opt-in and only work for dependencies installed in the current environment.
|
|
388
|
+
|
|
389
|
+
## Roadmap
|
|
390
|
+
|
|
391
|
+
The next serious versions should add:
|
|
392
|
+
|
|
393
|
+
1. Deeper entrypoint startup benchmarks with clearer default-path waste attribution.
|
|
394
|
+
2. `project-doctor fix --lazy-imports` with AST-safe rewrites and backups.
|
|
395
|
+
3. Lockfile awareness for Poetry, PDM, and pip-tools.
|
|
396
|
+
4. Docker/image-size analysis.
|
|
397
|
+
5. Richer package-name/import-name mapping.
|
|
398
|
+
6. Profiler integration for hot-loop acceleration suggestions.
|