gwc-pybundle 0.4.2__tar.gz → 1.1.1__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.
Potentially problematic release.
This version of gwc-pybundle might be problematic. Click here for more details.
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/PKG-INFO +261 -13
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/README.md +259 -11
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/gwc_pybundle.egg-info/PKG-INFO +261 -13
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/gwc_pybundle.egg-info/SOURCES.txt +6 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/cli.py +81 -17
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/context.py +69 -0
- gwc_pybundle-1.1.1/pybundle/filters.py +172 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/policy.py +22 -84
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/profiles.py +80 -17
- gwc_pybundle-1.1.1/pybundle/roadmap_model.py +42 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/roadmap_scan.py +55 -22
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/runner.py +8 -2
- gwc_pybundle-1.1.1/pybundle/steps/__init__.py +26 -0
- gwc_pybundle-1.1.1/pybundle/steps/bandit.py +74 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/copy_pack.py +99 -118
- gwc_pybundle-1.1.1/pybundle/steps/coverage.py +95 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/handoff_md.py +7 -6
- gwc_pybundle-1.1.1/pybundle/steps/pip_audit.py +47 -0
- gwc_pybundle-1.1.1/pybundle/steps/pylance.py +337 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/roadmap.py +50 -55
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/tree.py +12 -32
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pyproject.toml +2 -2
- gwc_pybundle-0.4.2/pybundle/roadmap_model.py +0 -38
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/LICENSE.md +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/gwc_pybundle.egg-info/dependency_links.txt +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/gwc_pybundle.egg-info/entry_points.txt +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/gwc_pybundle.egg-info/top_level.txt +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/__init__.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/__main__.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/doctor.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/manifest.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/packaging.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/root_detect.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/base.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/compileall.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/context_expand.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/error_refs.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/mypy.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/pytest.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/repro_md.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/rg_scans.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/ruff.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/steps/shell.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/pybundle/tools.py +0 -0
- {gwc_pybundle-0.4.2 → gwc_pybundle-1.1.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gwc-pybundle
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.1.1
|
|
4
4
|
Summary: Deterministic Python project context bundling for humans, automation, and AI
|
|
5
5
|
Author: Jessica Brown
|
|
6
6
|
License: The MIT License (MIT)
|
|
@@ -31,7 +31,7 @@ License: The MIT License (MIT)
|
|
|
31
31
|
Project-URL: Homepage, https://github.com/girls-whocode/pybundle
|
|
32
32
|
Project-URL: Repository, https://github.com/girls-whocode/pybundle
|
|
33
33
|
Project-URL: Issues, https://github.com/girls-whocode/pybundle/issues
|
|
34
|
-
Classifier: Development Status ::
|
|
34
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
35
35
|
Classifier: Intended Audience :: Developers
|
|
36
36
|
Classifier: License :: OSI Approved :: MIT License
|
|
37
37
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -47,9 +47,21 @@ Description-Content-Type: text/markdown
|
|
|
47
47
|
License-File: LICENSE.md
|
|
48
48
|
Dynamic: license-file
|
|
49
49
|
|
|
50
|
-
# 🧳 pybundle
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
# 🧳 pybundle [](https://pypi.org/project/gwc-pybundle/)
|
|
51
|
+

|
|
52
|
+
|
|
53
|
+
[](https://pypi.org/project/gwc-pybundle/)
|
|
54
|
+
[](LICENSE.md)
|
|
55
|
+
[](https://pepy.tech/projects/gwc-pybundle)
|
|
56
|
+

|
|
57
|
+
|
|
58
|
+
[](https://github.com/girls-whocode/pybundle/actions)
|
|
59
|
+
[](https://github.com/astral-sh/ruff)
|
|
60
|
+
[](https://mypy-lang.org/)
|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
**pybundle** is a deterministic, automation-friendly CLI that captures Python project context into a single, reproducible bundle — ideal for debugging, CI artifacts, audits, and AI-assisted workflows.
|
|
53
65
|
|
|
54
66
|
It produces **machine-readable outputs first**, with optional human-readable summaries layered on top.
|
|
55
67
|
|
|
@@ -111,7 +123,8 @@ For humans, automation, and AI alike.
|
|
|
111
123
|
* 🧾 **Structured summaries** (`SUMMARY.json`)
|
|
112
124
|
* 🧭 **Respects `.gitignore`** exactly when available
|
|
113
125
|
* 🛑 **Safely ignores virtualenvs and caches** (even with non-standard names)
|
|
114
|
-
* 🔍 Optional tooling checks (ruff, mypy, pytest,
|
|
126
|
+
* 🔍 Optional tooling checks (ruff, mypy, pytest, pylance, bandit, pip-audit, coverage)
|
|
127
|
+
* 🛡️ Security scanning (bandit for code issues, pip-audit for dependency CVEs)
|
|
115
128
|
* 🧪 Deterministic output (stable paths, timestamps, schemas)
|
|
116
129
|
* 🔒 Secret-safe (optional redaction)
|
|
117
130
|
|
|
@@ -125,7 +138,7 @@ At minimum, a bundle contains:
|
|
|
125
138
|
MANIFEST.json # stable, machine-readable metadata
|
|
126
139
|
SUMMARY.json # structured summary of collected data
|
|
127
140
|
src/ # filtered project source snapshot
|
|
128
|
-
logs/ # tool outputs (ruff, mypy,
|
|
141
|
+
logs/ # tool outputs (ruff, mypy, pytest, pylance, bandit, pip-audit, coverage, rg scans)
|
|
129
142
|
meta/ # environment + tool detection
|
|
130
143
|
```
|
|
131
144
|
|
|
@@ -157,7 +170,10 @@ Create a dedicated requirements file in the root of your project:
|
|
|
157
170
|
ruff
|
|
158
171
|
mypy
|
|
159
172
|
pytest
|
|
160
|
-
|
|
173
|
+
pytest-cov
|
|
174
|
+
bandit
|
|
175
|
+
pip-audit
|
|
176
|
+
gwc-pybundle==1.1.1
|
|
161
177
|
```
|
|
162
178
|
|
|
163
179
|
Then install:
|
|
@@ -194,7 +210,7 @@ See **Usage** for more details.
|
|
|
194
210
|
#### From GitHub
|
|
195
211
|
|
|
196
212
|
```bash
|
|
197
|
-
pip install "gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@
|
|
213
|
+
pip install "gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@v1.1.1"
|
|
198
214
|
```
|
|
199
215
|
|
|
200
216
|
Pinning to a tag ensures reproducible behavior.
|
|
@@ -225,7 +241,7 @@ Available profiles include:
|
|
|
225
241
|
|
|
226
242
|
* `analysis` - **full diagnostics** (lint, type-check, tests, scans)
|
|
227
243
|
* `debug` - **analysis + additional environment validation**
|
|
228
|
-
* `backup` - **minimal environment snapshot**
|
|
244
|
+
* `backup` - **minimal source + environment snapshot** (no analysis tools)
|
|
229
245
|
* `ai` - **AI-optimized context bundle** (lean, source-first)
|
|
230
246
|
|
|
231
247
|
To list all available profiles:
|
|
@@ -239,6 +255,132 @@ Profiles are always invoked via:
|
|
|
239
255
|
```bash
|
|
240
256
|
pybundle run <profile>
|
|
241
257
|
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
### 💾 Backup profile
|
|
262
|
+
|
|
263
|
+
The `backup` profile creates a minimal, lightweight snapshot ideal for version archival or disaster recovery.
|
|
264
|
+
|
|
265
|
+
Run it with:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
pybundle run backup
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### What `backup` includes
|
|
272
|
+
|
|
273
|
+
* ✅ Full source code snapshot (respects `.gitignore`)
|
|
274
|
+
* ✅ Git status and diff (`meta/00_git_status.txt`, `meta/01_git_diff.txt`)
|
|
275
|
+
* ✅ Python version (`meta/20_python_version.txt`)
|
|
276
|
+
* ✅ Installed packages (`meta/22_pip_freeze.txt`)
|
|
277
|
+
* ✅ Copy manifest (`meta/50_copy_manifest.txt`)
|
|
278
|
+
* ❌ No linting, type-checking, or tests
|
|
279
|
+
* ❌ No security scanning
|
|
280
|
+
* ❌ No ripgrep scans
|
|
281
|
+
|
|
282
|
+
The result is a **fast, small, restorable archive** with just source code and environment context.
|
|
283
|
+
|
|
284
|
+
#### Restoring a backup
|
|
285
|
+
|
|
286
|
+
Backups are created as either `.zip` or `.tar.gz` archives (see Archive Format below).
|
|
287
|
+
|
|
288
|
+
To extract and inspect:
|
|
289
|
+
|
|
290
|
+
**For .zip archives:**
|
|
291
|
+
```bash
|
|
292
|
+
# Look for filename with *_backup_<TIMESTAMP>.zip
|
|
293
|
+
unzip <FILENAME>.zip -d restored/
|
|
294
|
+
cd restored/<FILENAME>/
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**For .tar.gz archives:**
|
|
298
|
+
```bash
|
|
299
|
+
# Look for filename with *_backup_<TIMESTAMP>.tar.gz
|
|
300
|
+
tar -xzf <FILENAME>.tar.gz -C restored/
|
|
301
|
+
cd restored/<FILENAME>/
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Inside the extracted directory:
|
|
305
|
+
|
|
306
|
+
```text
|
|
307
|
+
src/ # Your project source code
|
|
308
|
+
meta/
|
|
309
|
+
00_git_status.txt # Git working tree status at backup time
|
|
310
|
+
01_git_diff.txt # Uncommitted changes (if any)
|
|
311
|
+
20_python_version.txt # Python version used
|
|
312
|
+
22_pip_freeze.txt # Exact package versions
|
|
313
|
+
50_copy_manifest.txt # List of files included
|
|
314
|
+
MANIFEST.json # Machine-readable metadata
|
|
315
|
+
SUMMARY.json # Structured summary
|
|
316
|
+
RUN_LOG.txt # Execution log
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The `src/` directory contains your complete project structure.
|
|
320
|
+
The `meta/22_pip_freeze.txt` file can be used to recreate the exact environment:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
python -m venv venv
|
|
324
|
+
source venv/bin/activate # or venv\Scripts\activate on Windows
|
|
325
|
+
pip install -r meta/22_pip_freeze.txt
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Then copy your source code back:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
cp -r src/* /path/to/your/project/
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
#### Archive format fallback
|
|
335
|
+
|
|
336
|
+
pybundle uses **zip** by default for maximum portability.
|
|
337
|
+
|
|
338
|
+
If the `zip` command is not available on your system, pybundle **automatically falls back to tar.gz** format without requiring configuration.
|
|
339
|
+
|
|
340
|
+
This ensures backups can be created on any system, regardless of installed compression tools.
|
|
341
|
+
|
|
342
|
+
To explicitly control the format:
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
pybundle run backup --format zip # Force zip (requires zip command)
|
|
346
|
+
pybundle run backup --format tar.gz # Force tar.gz (requires tar command)
|
|
347
|
+
pybundle run backup --format auto # Auto-detect (default behavior)
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Both formats preserve the same internal structure and metadata.
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
### 🔍 Analysis Tools
|
|
355
|
+
|
|
356
|
+
The `analysis` and `debug` profiles run comprehensive quality and security checks:
|
|
357
|
+
|
|
358
|
+
#### Code Quality
|
|
359
|
+
* **ruff** - Fast Python linter and formatter checks
|
|
360
|
+
* **mypy** - Static type checking for type hints
|
|
361
|
+
* **pylance** - Syntax error detection and import analysis
|
|
362
|
+
|
|
363
|
+
#### Testing & Coverage
|
|
364
|
+
* **pytest** - Test execution and results
|
|
365
|
+
* **coverage** - Code coverage analysis (shows tested vs untested code)
|
|
366
|
+
|
|
367
|
+
#### Security
|
|
368
|
+
* **bandit** - Security vulnerability scanning for Python code
|
|
369
|
+
* **pip-audit** - Dependency vulnerability checking against known CVEs
|
|
370
|
+
|
|
371
|
+
#### Pattern Scanning
|
|
372
|
+
* **ripgrep scans** - TODO detection, print statements, bare excepts
|
|
373
|
+
|
|
374
|
+
All tools gracefully skip if not installed. Install recommended tools:
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
pip install ruff mypy pytest pytest-cov bandit pip-audit
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
For ripgrep (system dependency):
|
|
381
|
+
* macOS: `brew install ripgrep`
|
|
382
|
+
* Ubuntu/Debian: `sudo apt install ripgrep`
|
|
383
|
+
|
|
242
384
|
---
|
|
243
385
|
|
|
244
386
|
### 🤖 AI profile (NEW)
|
|
@@ -311,7 +453,11 @@ Tool execution can be selectively disabled:
|
|
|
311
453
|
```bash
|
|
312
454
|
--no-ruff
|
|
313
455
|
--no-mypy
|
|
456
|
+
--no-pylance
|
|
314
457
|
--no-pytest
|
|
458
|
+
--no-bandit
|
|
459
|
+
--no-pip-audit
|
|
460
|
+
--no-coverage
|
|
315
461
|
--no-rg
|
|
316
462
|
--no-error-refs
|
|
317
463
|
--no-context
|
|
@@ -373,7 +519,109 @@ pybundle falls back to safe structural rules:
|
|
|
373
519
|
* detects virtual environments by structure (`pyvenv.cfg`, `bin/activate`), not by name
|
|
374
520
|
→ works with `.venv`, `.pybundle-venv`, `env-prod-2025`, etc.
|
|
375
521
|
|
|
376
|
-
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## 🧾 Machine-Readable Output (`--json`)
|
|
525
|
+
|
|
526
|
+
All `pybundle` commands support a **machine-readable JSON output mode** via the `--json` flag.
|
|
527
|
+
|
|
528
|
+
When enabled, `pybundle` emits **exactly one JSON object to stdout**, with a **stable schema** intended for:
|
|
529
|
+
|
|
530
|
+
* CI pipelines
|
|
531
|
+
* automation scripts
|
|
532
|
+
* external tooling
|
|
533
|
+
* AI orchestration
|
|
534
|
+
* reproducible analysis
|
|
535
|
+
|
|
536
|
+
No human text, spinners, or formatting are mixed into the output.
|
|
537
|
+
|
|
538
|
+
### Example
|
|
539
|
+
|
|
540
|
+
```bash
|
|
541
|
+
pybundle run analysis --json
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
Output:
|
|
545
|
+
|
|
546
|
+
```json
|
|
547
|
+
{
|
|
548
|
+
"status": "ok",
|
|
549
|
+
"command": "run",
|
|
550
|
+
"profile": "analysis",
|
|
551
|
+
"files_included": 39,
|
|
552
|
+
"files_excluded": 0,
|
|
553
|
+
"duration_ms": 394,
|
|
554
|
+
"bundle_path": "/home/jessica/repositories/python/pybundle/artifacts/pybundle_analysis_20260103T102440Z.zip"
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
The same structure applies to **all profiles**:
|
|
559
|
+
|
|
560
|
+
```bash
|
|
561
|
+
pybundle run ai --json
|
|
562
|
+
pybundle run debug --json
|
|
563
|
+
pybundle run backup --json
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
### JSON Field Definitions
|
|
569
|
+
|
|
570
|
+
| Field | Description |
|
|
571
|
+
| ---------------- | -------------------------------------------------- |
|
|
572
|
+
| `status` | `"ok"` or `"fail"` based on execution result |
|
|
573
|
+
| `command` | The command executed (`run` or `doctor`) |
|
|
574
|
+
| `profile` | The profile used (`analysis`, `ai`, `debug`, etc.) |
|
|
575
|
+
| `files_included` | Number of files copied into the bundle |
|
|
576
|
+
| `files_excluded` | Number of *evaluated* files skipped by policy |
|
|
577
|
+
| `duration_ms` | Total execution time in milliseconds |
|
|
578
|
+
| `bundle_path` | Absolute path to the generated archive |
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
### Important Semantics: `files_excluded`
|
|
583
|
+
|
|
584
|
+
`files_excluded` **does not** mean “everything in the repository that was not bundled.”
|
|
585
|
+
|
|
586
|
+
Instead, it means:
|
|
587
|
+
|
|
588
|
+
> Files that were **eligible under the active profile’s policy** and were *explicitly skipped* after evaluation.
|
|
589
|
+
|
|
590
|
+
Files and directories that are **intentionally out of scope** — such as:
|
|
591
|
+
|
|
592
|
+
* `.git/`
|
|
593
|
+
* `node_modules/`
|
|
594
|
+
* virtual environments
|
|
595
|
+
* build artifacts
|
|
596
|
+
* caches
|
|
597
|
+
|
|
598
|
+
are **never considered**, and therefore are **not counted as excluded**.
|
|
599
|
+
|
|
600
|
+
This design keeps metrics honest and avoids inflating counts with known-irrelevant infrastructure.
|
|
601
|
+
|
|
602
|
+
A value of `files_excluded = 0` simply means:
|
|
603
|
+
|
|
604
|
+
> *Everything that was evaluated was worth keeping.*
|
|
605
|
+
|
|
606
|
+
This is expected and normal for clean, well-structured projects — especially in `ai` mode.
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
### JSON Stability Guarantee
|
|
611
|
+
|
|
612
|
+
The JSON schema emitted by `--json` is considered **part of the public API**.
|
|
613
|
+
|
|
614
|
+
Starting with **v1.0**, field names and meanings will remain stable.
|
|
615
|
+
New fields may be added, but existing fields will not be renamed or removed.
|
|
616
|
+
|
|
617
|
+
This allows `pybundle` to be safely embedded into:
|
|
618
|
+
|
|
619
|
+
* CI workflows
|
|
620
|
+
* automation scripts
|
|
621
|
+
* AI pipelines
|
|
622
|
+
* external tooling
|
|
623
|
+
|
|
624
|
+
without fear of breaking changes.
|
|
377
625
|
|
|
378
626
|
---
|
|
379
627
|
|
|
@@ -446,7 +694,7 @@ pybundle follows **Semantic Versioning**.
|
|
|
446
694
|
Pinned Git tags are recommended when used as a dependency:
|
|
447
695
|
|
|
448
696
|
```txt
|
|
449
|
-
gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@
|
|
697
|
+
gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@v1.1.1
|
|
450
698
|
```
|
|
451
699
|
|
|
452
700
|
---
|
|
@@ -469,7 +717,7 @@ The project name, imports, and CLI remain **`pybundle`**.
|
|
|
469
717
|
pip install gwc-pybundle
|
|
470
718
|
pybundle run analysis
|
|
471
719
|
```
|
|
472
|
-
|
|
720
|
+
Look in the autocreated `artifacts/` folder.
|
|
473
721
|
|
|
474
722
|
## 📄 License
|
|
475
723
|
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
# 🧳 pybundle
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# 🧳 pybundle [](https://pypi.org/project/gwc-pybundle/)
|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
[](https://pypi.org/project/gwc-pybundle/)
|
|
5
|
+
[](LICENSE.md)
|
|
6
|
+
[](https://pepy.tech/projects/gwc-pybundle)
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
[](https://github.com/girls-whocode/pybundle/actions)
|
|
10
|
+
[](https://github.com/astral-sh/ruff)
|
|
11
|
+
[](https://mypy-lang.org/)
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
**pybundle** is a deterministic, automation-friendly CLI that captures Python project context into a single, reproducible bundle — ideal for debugging, CI artifacts, audits, and AI-assisted workflows.
|
|
4
16
|
|
|
5
17
|
It produces **machine-readable outputs first**, with optional human-readable summaries layered on top.
|
|
6
18
|
|
|
@@ -62,7 +74,8 @@ For humans, automation, and AI alike.
|
|
|
62
74
|
* 🧾 **Structured summaries** (`SUMMARY.json`)
|
|
63
75
|
* 🧭 **Respects `.gitignore`** exactly when available
|
|
64
76
|
* 🛑 **Safely ignores virtualenvs and caches** (even with non-standard names)
|
|
65
|
-
* 🔍 Optional tooling checks (ruff, mypy, pytest,
|
|
77
|
+
* 🔍 Optional tooling checks (ruff, mypy, pytest, pylance, bandit, pip-audit, coverage)
|
|
78
|
+
* 🛡️ Security scanning (bandit for code issues, pip-audit for dependency CVEs)
|
|
66
79
|
* 🧪 Deterministic output (stable paths, timestamps, schemas)
|
|
67
80
|
* 🔒 Secret-safe (optional redaction)
|
|
68
81
|
|
|
@@ -76,7 +89,7 @@ At minimum, a bundle contains:
|
|
|
76
89
|
MANIFEST.json # stable, machine-readable metadata
|
|
77
90
|
SUMMARY.json # structured summary of collected data
|
|
78
91
|
src/ # filtered project source snapshot
|
|
79
|
-
logs/ # tool outputs (ruff, mypy,
|
|
92
|
+
logs/ # tool outputs (ruff, mypy, pytest, pylance, bandit, pip-audit, coverage, rg scans)
|
|
80
93
|
meta/ # environment + tool detection
|
|
81
94
|
```
|
|
82
95
|
|
|
@@ -108,7 +121,10 @@ Create a dedicated requirements file in the root of your project:
|
|
|
108
121
|
ruff
|
|
109
122
|
mypy
|
|
110
123
|
pytest
|
|
111
|
-
|
|
124
|
+
pytest-cov
|
|
125
|
+
bandit
|
|
126
|
+
pip-audit
|
|
127
|
+
gwc-pybundle==1.1.1
|
|
112
128
|
```
|
|
113
129
|
|
|
114
130
|
Then install:
|
|
@@ -145,7 +161,7 @@ See **Usage** for more details.
|
|
|
145
161
|
#### From GitHub
|
|
146
162
|
|
|
147
163
|
```bash
|
|
148
|
-
pip install "gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@
|
|
164
|
+
pip install "gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@v1.1.1"
|
|
149
165
|
```
|
|
150
166
|
|
|
151
167
|
Pinning to a tag ensures reproducible behavior.
|
|
@@ -176,7 +192,7 @@ Available profiles include:
|
|
|
176
192
|
|
|
177
193
|
* `analysis` - **full diagnostics** (lint, type-check, tests, scans)
|
|
178
194
|
* `debug` - **analysis + additional environment validation**
|
|
179
|
-
* `backup` - **minimal environment snapshot**
|
|
195
|
+
* `backup` - **minimal source + environment snapshot** (no analysis tools)
|
|
180
196
|
* `ai` - **AI-optimized context bundle** (lean, source-first)
|
|
181
197
|
|
|
182
198
|
To list all available profiles:
|
|
@@ -190,6 +206,132 @@ Profiles are always invoked via:
|
|
|
190
206
|
```bash
|
|
191
207
|
pybundle run <profile>
|
|
192
208
|
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### 💾 Backup profile
|
|
213
|
+
|
|
214
|
+
The `backup` profile creates a minimal, lightweight snapshot ideal for version archival or disaster recovery.
|
|
215
|
+
|
|
216
|
+
Run it with:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
pybundle run backup
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### What `backup` includes
|
|
223
|
+
|
|
224
|
+
* ✅ Full source code snapshot (respects `.gitignore`)
|
|
225
|
+
* ✅ Git status and diff (`meta/00_git_status.txt`, `meta/01_git_diff.txt`)
|
|
226
|
+
* ✅ Python version (`meta/20_python_version.txt`)
|
|
227
|
+
* ✅ Installed packages (`meta/22_pip_freeze.txt`)
|
|
228
|
+
* ✅ Copy manifest (`meta/50_copy_manifest.txt`)
|
|
229
|
+
* ❌ No linting, type-checking, or tests
|
|
230
|
+
* ❌ No security scanning
|
|
231
|
+
* ❌ No ripgrep scans
|
|
232
|
+
|
|
233
|
+
The result is a **fast, small, restorable archive** with just source code and environment context.
|
|
234
|
+
|
|
235
|
+
#### Restoring a backup
|
|
236
|
+
|
|
237
|
+
Backups are created as either `.zip` or `.tar.gz` archives (see Archive Format below).
|
|
238
|
+
|
|
239
|
+
To extract and inspect:
|
|
240
|
+
|
|
241
|
+
**For .zip archives:**
|
|
242
|
+
```bash
|
|
243
|
+
# Look for filename with *_backup_<TIMESTAMP>.zip
|
|
244
|
+
unzip <FILENAME>.zip -d restored/
|
|
245
|
+
cd restored/<FILENAME>/
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**For .tar.gz archives:**
|
|
249
|
+
```bash
|
|
250
|
+
# Look for filename with *_backup_<TIMESTAMP>.tar.gz
|
|
251
|
+
tar -xzf <FILENAME>.tar.gz -C restored/
|
|
252
|
+
cd restored/<FILENAME>/
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Inside the extracted directory:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
src/ # Your project source code
|
|
259
|
+
meta/
|
|
260
|
+
00_git_status.txt # Git working tree status at backup time
|
|
261
|
+
01_git_diff.txt # Uncommitted changes (if any)
|
|
262
|
+
20_python_version.txt # Python version used
|
|
263
|
+
22_pip_freeze.txt # Exact package versions
|
|
264
|
+
50_copy_manifest.txt # List of files included
|
|
265
|
+
MANIFEST.json # Machine-readable metadata
|
|
266
|
+
SUMMARY.json # Structured summary
|
|
267
|
+
RUN_LOG.txt # Execution log
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
The `src/` directory contains your complete project structure.
|
|
271
|
+
The `meta/22_pip_freeze.txt` file can be used to recreate the exact environment:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
python -m venv venv
|
|
275
|
+
source venv/bin/activate # or venv\Scripts\activate on Windows
|
|
276
|
+
pip install -r meta/22_pip_freeze.txt
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Then copy your source code back:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
cp -r src/* /path/to/your/project/
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### Archive format fallback
|
|
286
|
+
|
|
287
|
+
pybundle uses **zip** by default for maximum portability.
|
|
288
|
+
|
|
289
|
+
If the `zip` command is not available on your system, pybundle **automatically falls back to tar.gz** format without requiring configuration.
|
|
290
|
+
|
|
291
|
+
This ensures backups can be created on any system, regardless of installed compression tools.
|
|
292
|
+
|
|
293
|
+
To explicitly control the format:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
pybundle run backup --format zip # Force zip (requires zip command)
|
|
297
|
+
pybundle run backup --format tar.gz # Force tar.gz (requires tar command)
|
|
298
|
+
pybundle run backup --format auto # Auto-detect (default behavior)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Both formats preserve the same internal structure and metadata.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
### 🔍 Analysis Tools
|
|
306
|
+
|
|
307
|
+
The `analysis` and `debug` profiles run comprehensive quality and security checks:
|
|
308
|
+
|
|
309
|
+
#### Code Quality
|
|
310
|
+
* **ruff** - Fast Python linter and formatter checks
|
|
311
|
+
* **mypy** - Static type checking for type hints
|
|
312
|
+
* **pylance** - Syntax error detection and import analysis
|
|
313
|
+
|
|
314
|
+
#### Testing & Coverage
|
|
315
|
+
* **pytest** - Test execution and results
|
|
316
|
+
* **coverage** - Code coverage analysis (shows tested vs untested code)
|
|
317
|
+
|
|
318
|
+
#### Security
|
|
319
|
+
* **bandit** - Security vulnerability scanning for Python code
|
|
320
|
+
* **pip-audit** - Dependency vulnerability checking against known CVEs
|
|
321
|
+
|
|
322
|
+
#### Pattern Scanning
|
|
323
|
+
* **ripgrep scans** - TODO detection, print statements, bare excepts
|
|
324
|
+
|
|
325
|
+
All tools gracefully skip if not installed. Install recommended tools:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
pip install ruff mypy pytest pytest-cov bandit pip-audit
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
For ripgrep (system dependency):
|
|
332
|
+
* macOS: `brew install ripgrep`
|
|
333
|
+
* Ubuntu/Debian: `sudo apt install ripgrep`
|
|
334
|
+
|
|
193
335
|
---
|
|
194
336
|
|
|
195
337
|
### 🤖 AI profile (NEW)
|
|
@@ -262,7 +404,11 @@ Tool execution can be selectively disabled:
|
|
|
262
404
|
```bash
|
|
263
405
|
--no-ruff
|
|
264
406
|
--no-mypy
|
|
407
|
+
--no-pylance
|
|
265
408
|
--no-pytest
|
|
409
|
+
--no-bandit
|
|
410
|
+
--no-pip-audit
|
|
411
|
+
--no-coverage
|
|
266
412
|
--no-rg
|
|
267
413
|
--no-error-refs
|
|
268
414
|
--no-context
|
|
@@ -324,7 +470,109 @@ pybundle falls back to safe structural rules:
|
|
|
324
470
|
* detects virtual environments by structure (`pyvenv.cfg`, `bin/activate`), not by name
|
|
325
471
|
→ works with `.venv`, `.pybundle-venv`, `env-prod-2025`, etc.
|
|
326
472
|
|
|
327
|
-
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## 🧾 Machine-Readable Output (`--json`)
|
|
476
|
+
|
|
477
|
+
All `pybundle` commands support a **machine-readable JSON output mode** via the `--json` flag.
|
|
478
|
+
|
|
479
|
+
When enabled, `pybundle` emits **exactly one JSON object to stdout**, with a **stable schema** intended for:
|
|
480
|
+
|
|
481
|
+
* CI pipelines
|
|
482
|
+
* automation scripts
|
|
483
|
+
* external tooling
|
|
484
|
+
* AI orchestration
|
|
485
|
+
* reproducible analysis
|
|
486
|
+
|
|
487
|
+
No human text, spinners, or formatting are mixed into the output.
|
|
488
|
+
|
|
489
|
+
### Example
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
pybundle run analysis --json
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
Output:
|
|
496
|
+
|
|
497
|
+
```json
|
|
498
|
+
{
|
|
499
|
+
"status": "ok",
|
|
500
|
+
"command": "run",
|
|
501
|
+
"profile": "analysis",
|
|
502
|
+
"files_included": 39,
|
|
503
|
+
"files_excluded": 0,
|
|
504
|
+
"duration_ms": 394,
|
|
505
|
+
"bundle_path": "/home/jessica/repositories/python/pybundle/artifacts/pybundle_analysis_20260103T102440Z.zip"
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
The same structure applies to **all profiles**:
|
|
510
|
+
|
|
511
|
+
```bash
|
|
512
|
+
pybundle run ai --json
|
|
513
|
+
pybundle run debug --json
|
|
514
|
+
pybundle run backup --json
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
### JSON Field Definitions
|
|
520
|
+
|
|
521
|
+
| Field | Description |
|
|
522
|
+
| ---------------- | -------------------------------------------------- |
|
|
523
|
+
| `status` | `"ok"` or `"fail"` based on execution result |
|
|
524
|
+
| `command` | The command executed (`run` or `doctor`) |
|
|
525
|
+
| `profile` | The profile used (`analysis`, `ai`, `debug`, etc.) |
|
|
526
|
+
| `files_included` | Number of files copied into the bundle |
|
|
527
|
+
| `files_excluded` | Number of *evaluated* files skipped by policy |
|
|
528
|
+
| `duration_ms` | Total execution time in milliseconds |
|
|
529
|
+
| `bundle_path` | Absolute path to the generated archive |
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
### Important Semantics: `files_excluded`
|
|
534
|
+
|
|
535
|
+
`files_excluded` **does not** mean “everything in the repository that was not bundled.”
|
|
536
|
+
|
|
537
|
+
Instead, it means:
|
|
538
|
+
|
|
539
|
+
> Files that were **eligible under the active profile’s policy** and were *explicitly skipped* after evaluation.
|
|
540
|
+
|
|
541
|
+
Files and directories that are **intentionally out of scope** — such as:
|
|
542
|
+
|
|
543
|
+
* `.git/`
|
|
544
|
+
* `node_modules/`
|
|
545
|
+
* virtual environments
|
|
546
|
+
* build artifacts
|
|
547
|
+
* caches
|
|
548
|
+
|
|
549
|
+
are **never considered**, and therefore are **not counted as excluded**.
|
|
550
|
+
|
|
551
|
+
This design keeps metrics honest and avoids inflating counts with known-irrelevant infrastructure.
|
|
552
|
+
|
|
553
|
+
A value of `files_excluded = 0` simply means:
|
|
554
|
+
|
|
555
|
+
> *Everything that was evaluated was worth keeping.*
|
|
556
|
+
|
|
557
|
+
This is expected and normal for clean, well-structured projects — especially in `ai` mode.
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
### JSON Stability Guarantee
|
|
562
|
+
|
|
563
|
+
The JSON schema emitted by `--json` is considered **part of the public API**.
|
|
564
|
+
|
|
565
|
+
Starting with **v1.0**, field names and meanings will remain stable.
|
|
566
|
+
New fields may be added, but existing fields will not be renamed or removed.
|
|
567
|
+
|
|
568
|
+
This allows `pybundle` to be safely embedded into:
|
|
569
|
+
|
|
570
|
+
* CI workflows
|
|
571
|
+
* automation scripts
|
|
572
|
+
* AI pipelines
|
|
573
|
+
* external tooling
|
|
574
|
+
|
|
575
|
+
without fear of breaking changes.
|
|
328
576
|
|
|
329
577
|
---
|
|
330
578
|
|
|
@@ -397,7 +645,7 @@ pybundle follows **Semantic Versioning**.
|
|
|
397
645
|
Pinned Git tags are recommended when used as a dependency:
|
|
398
646
|
|
|
399
647
|
```txt
|
|
400
|
-
gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@
|
|
648
|
+
gwc-pybundle @ git+https://github.com/girls-whocode/pybundle.git@v1.1.1
|
|
401
649
|
```
|
|
402
650
|
|
|
403
651
|
---
|
|
@@ -420,7 +668,7 @@ The project name, imports, and CLI remain **`pybundle`**.
|
|
|
420
668
|
pip install gwc-pybundle
|
|
421
669
|
pybundle run analysis
|
|
422
670
|
```
|
|
423
|
-
|
|
671
|
+
Look in the autocreated `artifacts/` folder.
|
|
424
672
|
|
|
425
673
|
## 📄 License
|
|
426
674
|
|