dirplot 0.3.0__tar.gz → 0.3.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.
Files changed (119) hide show
  1. {dirplot-0.3.0 → dirplot-0.3.1}/CHANGELOG.md +75 -28
  2. {dirplot-0.3.0 → dirplot-0.3.1}/PKG-INFO +19 -4
  3. {dirplot-0.3.0 → dirplot-0.3.1}/README.md +15 -3
  4. {dirplot-0.3.0 → dirplot-0.3.1}/SECURITY.md +1 -1
  5. {dirplot-0.3.0 → dirplot-0.3.1}/docs/ARCHIVES.md +65 -6
  6. {dirplot-0.3.0 → dirplot-0.3.1}/docs/EXAMPLES.md +10 -0
  7. {dirplot-0.3.0 → dirplot-0.3.1}/pyproject.toml +6 -2
  8. dirplot-0.3.1/scripts/make_fixtures.py +340 -0
  9. dirplot-0.3.1/src/dirplot/__main__.py +41 -0
  10. dirplot-0.3.1/src/dirplot/archives.py +359 -0
  11. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/github.py +56 -22
  12. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/main.py +66 -19
  13. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/render.py +112 -50
  14. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/scanner.py +18 -0
  15. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/svg_render.py +113 -57
  16. dirplot-0.3.1/tests/conftest.py +257 -0
  17. dirplot-0.3.1/tests/fixtures/sample.7z +0 -0
  18. dirplot-0.3.1/tests/fixtures/sample.a +0 -0
  19. dirplot-0.3.1/tests/fixtures/sample.aab +0 -0
  20. dirplot-0.3.1/tests/fixtures/sample.apk +0 -0
  21. dirplot-0.3.1/tests/fixtures/sample.cpio +0 -0
  22. dirplot-0.3.1/tests/fixtures/sample.ear +0 -0
  23. dirplot-0.3.1/tests/fixtures/sample.epub +0 -0
  24. dirplot-0.3.1/tests/fixtures/sample.ipa +0 -0
  25. dirplot-0.3.1/tests/fixtures/sample.iso +0 -0
  26. dirplot-0.3.1/tests/fixtures/sample.jar +0 -0
  27. dirplot-0.3.1/tests/fixtures/sample.nupkg +0 -0
  28. dirplot-0.3.1/tests/fixtures/sample.rar +0 -0
  29. {dirplot-0.3.0 → dirplot-0.3.1}/tests/fixtures/sample.tar.gz +0 -0
  30. dirplot-0.3.1/tests/fixtures/sample.tar.zst +0 -0
  31. {dirplot-0.3.0 → dirplot-0.3.1}/tests/fixtures/sample.tgz +0 -0
  32. dirplot-0.3.1/tests/fixtures/sample.tzst +0 -0
  33. dirplot-0.3.1/tests/fixtures/sample.vsix +0 -0
  34. dirplot-0.3.1/tests/fixtures/sample.war +0 -0
  35. dirplot-0.3.1/tests/fixtures/sample.whl +0 -0
  36. dirplot-0.3.1/tests/fixtures/sample.xar +0 -0
  37. dirplot-0.3.1/tests/fixtures/sample.xpi +0 -0
  38. dirplot-0.3.1/tests/fixtures/sample.zip +0 -0
  39. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_archives.py +222 -3
  40. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_cli.py +8 -0
  41. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_github.py +26 -3
  42. {dirplot-0.3.0 → dirplot-0.3.1}/uv.lock +17 -2
  43. dirplot-0.3.0/scripts/make_fixtures.py +0 -144
  44. dirplot-0.3.0/src/dirplot/__main__.py +0 -11
  45. dirplot-0.3.0/src/dirplot/archives.py +0 -225
  46. dirplot-0.3.0/tests/conftest.py +0 -132
  47. dirplot-0.3.0/tests/fixtures/sample.7z +0 -0
  48. dirplot-0.3.0/tests/fixtures/sample.apk +0 -0
  49. dirplot-0.3.0/tests/fixtures/sample.ear +0 -0
  50. dirplot-0.3.0/tests/fixtures/sample.epub +0 -0
  51. dirplot-0.3.0/tests/fixtures/sample.jar +0 -0
  52. dirplot-0.3.0/tests/fixtures/sample.rar +0 -0
  53. dirplot-0.3.0/tests/fixtures/sample.war +0 -0
  54. dirplot-0.3.0/tests/fixtures/sample.whl +0 -0
  55. dirplot-0.3.0/tests/fixtures/sample.xpi +0 -0
  56. dirplot-0.3.0/tests/fixtures/sample.zip +0 -0
  57. {dirplot-0.3.0 → dirplot-0.3.1}/.claude/settings.local.json +0 -0
  58. {dirplot-0.3.0 → dirplot-0.3.1}/.dockerignore +0 -0
  59. {dirplot-0.3.0 → dirplot-0.3.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  60. {dirplot-0.3.0 → dirplot-0.3.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  61. {dirplot-0.3.0 → dirplot-0.3.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  62. {dirplot-0.3.0 → dirplot-0.3.1}/.github/dependabot.yml +0 -0
  63. {dirplot-0.3.0 → dirplot-0.3.1}/.github/workflows/ci.yml +0 -0
  64. {dirplot-0.3.0 → dirplot-0.3.1}/.github/workflows/publish.yml +0 -0
  65. {dirplot-0.3.0 → dirplot-0.3.1}/.gitignore +0 -0
  66. {dirplot-0.3.0 → dirplot-0.3.1}/.ipynb_checkpoints/Untitled-checkpoint.ipynb +0 -0
  67. {dirplot-0.3.0 → dirplot-0.3.1}/.pre-commit-config.yaml +0 -0
  68. {dirplot-0.3.0 → dirplot-0.3.1}/.python-version +0 -0
  69. {dirplot-0.3.0 → dirplot-0.3.1}/CONTRIBUTING.md +0 -0
  70. {dirplot-0.3.0 → dirplot-0.3.1}/Dockerfile +0 -0
  71. {dirplot-0.3.0 → dirplot-0.3.1}/LICENSE +0 -0
  72. {dirplot-0.3.0 → dirplot-0.3.1}/Makefile +0 -0
  73. {dirplot-0.3.0 → dirplot-0.3.1}/TASKS.md~ +0 -0
  74. {dirplot-0.3.0 → dirplot-0.3.1}/docs/SSH_DESIGN.md +0 -0
  75. {dirplot-0.3.0 → dirplot-0.3.1}/docs/dirplot.png +0 -0
  76. {dirplot-0.3.0 → dirplot-0.3.1}/docs/docker.png +0 -0
  77. {dirplot-0.3.0 → dirplot-0.3.1}/docs/fastapi.png +0 -0
  78. {dirplot-0.3.0 → dirplot-0.3.1}/docs/flask.png +0 -0
  79. {dirplot-0.3.0 → dirplot-0.3.1}/docs/k8s.png +0 -0
  80. {dirplot-0.3.0 → dirplot-0.3.1}/docs/pypy.png +0 -0
  81. {dirplot-0.3.0 → dirplot-0.3.1}/docs/python.png +0 -0
  82. {dirplot-0.3.0 → dirplot-0.3.1}/docs/s3.png +0 -0
  83. {dirplot-0.3.0 → dirplot-0.3.1}/scripts/make_docs_images.sh +0 -0
  84. {dirplot-0.3.0 → dirplot-0.3.1}/scripts/open_terminals.sh +0 -0
  85. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/__init__.py +0 -0
  86. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/colors.py +0 -0
  87. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/display.py +0 -0
  88. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/docker.py +0 -0
  89. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/fonts/JetBrainsMono-Bold.ttf +0 -0
  90. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/fonts/JetBrainsMono-BoldItalic.ttf +0 -0
  91. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/fonts/JetBrainsMono-Italic.ttf +0 -0
  92. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/fonts/JetBrainsMono-Regular.ttf +0 -0
  93. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/fonts/OFL.txt +0 -0
  94. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/k8s.py +0 -0
  95. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/py.typed +0 -0
  96. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/s3.py +0 -0
  97. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/ssh.py +0 -0
  98. {dirplot-0.3.0 → dirplot-0.3.1}/src/dirplot/terminal.py +0 -0
  99. {dirplot-0.3.0 → dirplot-0.3.1}/src.svg +0 -0
  100. {dirplot-0.3.0 → dirplot-0.3.1}/tests/__init__.py +0 -0
  101. {dirplot-0.3.0 → dirplot-0.3.1}/tests/example/bar/bar.py +0 -0
  102. {dirplot-0.3.0 → dirplot-0.3.1}/tests/example/bar/baz.json +0 -0
  103. {dirplot-0.3.0 → dirplot-0.3.1}/tests/example/foo/foo.md +0 -0
  104. {dirplot-0.3.0 → dirplot-0.3.1}/tests/fixtures/sample.tar +0 -0
  105. {dirplot-0.3.0 → dirplot-0.3.1}/tests/fixtures/sample.tar.bz2 +0 -0
  106. {dirplot-0.3.0 → dirplot-0.3.1}/tests/fixtures/sample.tar.xz +0 -0
  107. {dirplot-0.3.0 → dirplot-0.3.1}/tests/fixtures/sample.tbz2 +0 -0
  108. {dirplot-0.3.0 → dirplot-0.3.1}/tests/fixtures/sample.txz +0 -0
  109. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_colors.py +0 -0
  110. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_display.py +0 -0
  111. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_docker.py +0 -0
  112. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_drawing.py +0 -0
  113. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_k8s.py +0 -0
  114. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_render.py +0 -0
  115. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_s3.py +0 -0
  116. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_scanner.py +0 -0
  117. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_ssh.py +0 -0
  118. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_svg_render.py +0 -0
  119. {dirplot-0.3.0 → dirplot-0.3.1}/tests/test_terminal.py +0 -0
@@ -7,6 +7,62 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - `github://` URI now accepts an optional subpath after the repository name, letting
13
+ you scan a subdirectory directly:
14
+ - `github://owner/repo/sub/path` — subpath on the default branch
15
+ - `github://owner/repo@ref/sub/path` — subpath on a specific branch, tag, or commit SHA
16
+ - `https://github.com/owner/repo/tree/branch/sub/path` — full GitHub URL form
17
+ - Tags and commit SHAs are supported wherever a branch ref was previously accepted
18
+ (e.g. `github://torvalds/linux@v6.12`), as the GitHub trees API accepts any git ref.
19
+ - `--legend N` replaces the old boolean `--legend/--no-legend` flag. It now shows a
20
+ **file-count legend** — a sorted list of the top N extensions by number of files,
21
+ with a coloured swatch and the file count for each entry:
22
+ - Pass `--legend` alone to use the default of 20 entries.
23
+ - Pass `--legend 10` for a custom limit.
24
+ - Omit the flag entirely to show no legend.
25
+ - The number of rows is also capped automatically so the box never overflows the
26
+ image, based on available vertical space and the current `--font-size`.
27
+ - Extensions with the same count are sorted alphabetically as a tiebreaker.
28
+ - When the total number of extensions exceeds the limit, a `(+N more)` line is
29
+ appended at the bottom of the box.
30
+
31
+ - The root tile header now includes a summary of the scanned tree after an em-dash
32
+ separator: `myproject — 124 files, 18 dirs, 4.0 MB (4,231,680 bytes)`.
33
+ Applies to both PNG and SVG output. The label is truncated with `…` when the tile
34
+ is too narrow to fit the full string.
35
+
36
+ - Greatly expanded archive format support via the new `libarchive-c` core dependency
37
+ (wraps the system libarchive C library):
38
+ - **New formats**: `.iso`, `.cpio`, `.xar`, `.pkg`, `.dmg`, `.img`, `.rpm`, `.cab`,
39
+ `.lha`, `.lzh`, `.a`, `.ar`, `.tar.zst`, `.tzst`
40
+ - **New ZIP aliases**: `.nupkg` (NuGet), `.vsix` (VS Code extension), `.ipa` (iOS app),
41
+ `.aab` (Android App Bundle)
42
+ - `.tar.zst` / `.tzst` routed through libarchive for consistent behaviour across all
43
+ supported Python versions (stdlib `tarfile` only gained zstd support in 3.12).
44
+ - `libarchive-c>=5.0` added as a core dependency alongside `py7zr` and `rarfile`.
45
+ Requires the system libarchive library:
46
+ `brew install libarchive` / `apt install libarchive-dev`.
47
+ - See [ARCHIVES.md](docs/ARCHIVES.md) for the full format table, platform notes, and
48
+ intentionally unsupported formats (`.deb`, UDIF `.dmg`).
49
+ - Encrypted archive handling:
50
+ - `--password` CLI option passes a passphrase upfront.
51
+ - If an archive turns out to be encrypted and no password was given, dirplot prompts
52
+ interactively (`Password:` hidden-input prompt) and retries — no need to re-run with a flag.
53
+ - A wrong password exits cleanly with `Error: incorrect password.`
54
+ - `PasswordRequired` exception exported from `dirplot.archives` for programmatic use.
55
+ - **Encryption behaviour by format** (since dirplot reads metadata only, never extracts):
56
+ - ZIP and 7z: central directory / file list is unencrypted by default → readable without
57
+ a password even for encrypted archives.
58
+ - RAR with header encryption (`-hp`): listing is hidden without password;
59
+ wrong password raises `PasswordRequired`.
60
+
61
+ ### Fixed
62
+
63
+ - `--version` moved back to the top-level `dirplot` command (was accidentally scoped
64
+ to `dirplot map` after the CLI was restructured into subcommands).
65
+
10
66
  ## [0.3.0] - 2026-03-10
11
67
 
12
68
  ### Added
@@ -22,33 +78,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
78
  the scanned path are traversed — the common case in k8s where images declare
23
79
  `VOLUME` entries that are always mounted on a separate filesystem.
24
80
  - Automatically falls back to a portable `sh` + `stat` loop on BusyBox/Alpine pods.
25
- - `github://owner/repo[@branch]` URI scheme for GitHub repository scanning. The old
26
- `github:owner/repo` shorthand has been removed.
27
- - File tiles now have a 1-px dark outline (60/255 below fill colour per channel) so
28
- adjacent same-coloured tiles — e.g. a directory full of extension-less files — are
29
- always visually distinct rather than blending into a single flat block.
30
-
31
- ### Changed
32
-
33
- - `docs/REMOTE-ACCESS.md` renamed to `docs/EXAMPLES.md`; Docker and Kubernetes pod
34
- sections added; images with captions added for all remote backends.
35
-
36
- ### Fixed
37
-
38
- - SVG tooltips now show the original byte count when `--log` is active, not the
39
- log-transformed layout value. `Node.original_size` is populated by `apply_log_sizes`
40
- for both file and directory nodes and is used by the SVG renderer for `data-size`.
41
- - GitHub error messages are now clear and actionable:
42
- - 401 explicitly says the token is invalid or expired.
43
- - 403 distinguishes rate-limit exceeded (with the 60 vs 5,000 req/h figures and a
44
- token hint) from a permissions failure on a private repository.
45
- - 404 now also hints that a token is required for private repositories (GitHub returns
46
- 404, not 403, for private repos accessed without authentication).
47
- - Errors are caught in the CLI and printed as a single `Error: …` line to stderr
48
- instead of showing a Python traceback.
49
-
50
- ### Added
51
-
52
81
  - Docker container scanning via `docker://container:/path` syntax — uses `docker exec`
53
82
  and `find` to build the tree without copying files out of the container. Works on any
54
83
  running container that has a POSIX shell and `find` (GNU or BusyBox). No extra
@@ -70,7 +99,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
70
99
  overlay (`gradientUnits="objectBoundingBox"`), defined once and shared across all tiles.
71
100
  Matches the ×1.20 highlight / ×0.80 shadow range of the PNG renderer.
72
101
  Disabled with `--no-cushion`.
73
- - `--format png|svg` CLI option; format is also auto-detected from the `--output` file extension.
102
+ - `--format png|svg` CLI option; format is also auto-detected from the `--output` file
103
+ extension.
74
104
  - `create_treemap_svg()` added to the public Python API (`from dirplot import create_treemap_svg`).
75
105
  - `drawsvg>=2.4` added as a core dependency.
76
106
  - Rename the treemap command to `map` (dirplot map <root>).
@@ -81,6 +111,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
81
111
  - Support for local archive files, .zip, tgz, .tar.xz, .rar, .7z, etc.
82
112
  - Include example archives for 17 different extentions for testing.
83
113
  - Comprehensive documentation.
114
+ - `github://owner/repo[@branch]` URI scheme for GitHub repository scanning. The old
115
+ `github:owner/repo` shorthand has been removed.
116
+ - File tiles now have a 1-px dark outline (60/255 below fill colour per channel) so
117
+ adjacent same-coloured tiles — e.g. a directory full of extension-less files — are
118
+ always visually distinct rather than blending into a single flat block.
119
+
120
+ ### Changed
121
+
122
+ - `docs/REMOTE-ACCESS.md` renamed to `docs/EXAMPLES.md`; Docker and Kubernetes pod
123
+ sections added; images with captions added for all remote backends.
124
+
125
+ ### Fixed
126
+
127
+ - SVG tooltips now show the original byte count when `--log` is active, not the
128
+ log-transformed layout value. `Node.original_size` is populated by `apply_log_sizes`
129
+ for both file and directory nodes and is used by the SVG renderer for `data-size`.
130
+ - GitHub error messages are now clear and actionable.
84
131
 
85
132
  ## [0.2.0] - 2026-03-09
86
133
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirplot
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Static treemap bitmaps for directory trees and archives, displayed as inline terminal images
5
5
  Project-URL: Repository, https://github.com/deeplook/dirplot
6
6
  License: MIT
@@ -26,6 +26,7 @@ Classifier: Topic :: Utilities
26
26
  Classifier: Typing :: Typed
27
27
  Requires-Python: >=3.10
28
28
  Requires-Dist: drawsvg>=2.4.1
29
+ Requires-Dist: libarchive-c>=5.0
29
30
  Requires-Dist: matplotlib>=3.7
30
31
  Requires-Dist: pillow>=9.0
31
32
  Requires-Dist: py7zr>=0.20
@@ -38,6 +39,8 @@ Requires-Dist: pre-commit>=3.0; extra == 'dev'
38
39
  Requires-Dist: pytest-cov>=5.0; extra == 'dev'
39
40
  Requires-Dist: pytest>=8.0; extra == 'dev'
40
41
  Requires-Dist: ruff>=0.4; extra == 'dev'
42
+ Provides-Extra: libarchive
43
+ Requires-Dist: libarchive-c>=5.3; extra == 'libarchive'
41
44
  Provides-Extra: s3
42
45
  Requires-Dist: boto3>=1.26; extra == 's3'
43
46
  Provides-Extra: ssh
@@ -71,7 +74,9 @@ Description-Content-Type: text/markdown
71
74
  - Save output to a PNG or SVG file with `--output`.
72
75
  - Exclude paths with `--exclude` (repeatable).
73
76
  - Works on macOS, Linux, and Windows; WSL2 fully supported.
74
- - Scan remote hosts over SSH (`pip install "dirplot[ssh]"`), AWS S3 buckets (`pip install "dirplot[s3]"`), any public/private GitHub repository, **running Docker containers**, or **Kubernetes pods** — all without extra dependencies beyond the respective CLI/SDK. See [EXAMPLES.md](docs/EXAMPLES.md).
77
+ - Scan remote hosts over SSH (`pip install "dirplot[ssh]"`), AWS S3 buckets (`pip install "dirplot[s3]"`), any public/private GitHub repository (including specific branch, tag, commit SHA, or subdirectory), **running Docker containers**, or **Kubernetes pods** — all without extra dependencies beyond the respective CLI/SDK. See [EXAMPLES.md](docs/EXAMPLES.md).
78
+ - Optional **file-count legend** (`--legend`) — a corner overlay listing the top extensions by number of files, with coloured swatches and counts, automatically sized to fit the image.
79
+ - **Wide archive support** — reads zip, tar (gz/bz2/xz/zst), 7z, rar, and via libarchive: iso, cpio, rpm, cab, lha/lzh, xar/pkg, a/ar, and all ZIP-based formats (jar, whl, apk, nupkg, vsix, ipa, …) as virtual directory trees without unpacking. Encrypted archives are handled gracefully: metadata-only reads work without a password for most formats; a password can be supplied with `--password` or entered interactively when needed.
75
80
 
76
81
  ## How It Works
77
82
 
@@ -138,6 +143,12 @@ dirplot map . --size 1920x1080 --output dirplot.png --no-show
138
143
  # Don't apply cushion shading — makes tiles look flat
139
144
  dirplot map . --no-cushion
140
145
 
146
+ # Show a file-count legend (top 20 extensions by default)
147
+ dirplot map . --legend
148
+
149
+ # Show a file-count legend limited to 10 entries
150
+ dirplot map . --legend 10
151
+
141
152
  # Save as an interactive SVG (hover highlight + floating tooltip)
142
153
  dirplot map . --output treemap.svg --no-show
143
154
 
@@ -153,7 +164,7 @@ dirplot map . --format svg --output treemap.svg --no-show
153
164
  | `--format` | `-f` | auto | Output format: `png` or `svg`. Auto-detected from `--output` extension |
154
165
  | `--show/--no-show` | | `--show` | Display the image after rendering |
155
166
  | `--inline` | | off | Display in terminal (protocol auto-detected; PNG only) |
156
- | `--legend/--no-legend` | | `--no-legend` | Show file-extension colour legend |
167
+ | `--legend [N]` | | off | Show file-count legend; `N` sets max entries (default: 20) |
157
168
  | `--font-size` | `-s` | `12` | Directory label font size in pixels |
158
169
  | `--colormap` | `-c` | `tab20` | Matplotlib colormap for unknown extensions |
159
170
  | `--exclude` | `-e` | — | Path to exclude (repeatable) |
@@ -161,6 +172,7 @@ dirplot map . --format svg --output treemap.svg --no-show
161
172
  | `--header/--no-header` | | `--header` | Print info lines before rendering |
162
173
  | `--cushion/--no-cushion` | | `--cushion` | Apply van Wijk cushion shading for a raised 3-D look |
163
174
  | `--log/--no-log` | | `--no-log` | Use log of file sizes for layout, making small files more visible |
175
+ | `--password` | | — | Password for encrypted archives; prompted interactively if not supplied and needed |
164
176
  | `--github-token` | | `$GITHUB_TOKEN` | GitHub personal access token for private repos or higher rate limits |
165
177
 
166
178
  ## Inline Display
@@ -186,7 +198,7 @@ The default mode (`--show`, no `--inline`) opens the PNG in the system viewer (`
186
198
 
187
199
  ## Archives
188
200
 
189
- dirplot can read local archive files (zip, tar, 7z, rar, and ZIP-based formats like jar, whl, apk) as treemap inputs without unpacking them. See [ARCHIVES.md](docs/ARCHIVES.md) for supported formats, dependencies, and RAR setup on macOS.
201
+ dirplot can read local archive files without unpacking them — zip, tar (gz/bz2/xz/zst), 7z, rar, and many more via libarchive (iso, cpio, rpm, cab, lha, xar, and all ZIP-based formats like jar, whl, apk, nupkg, vsix, ipa). See [ARCHIVES.md](docs/ARCHIVES.md) for the full list, dependencies, and platform notes.
190
202
 
191
203
  ```bash
192
204
  dirplot map project.zip
@@ -210,6 +222,7 @@ pip install "dirplot[s3]" # AWS S3 via boto3
210
222
  dirplot map ssh://alice@prod.example.com/var/www
211
223
  dirplot map s3://noaa-ghcn-pds --no-sign
212
224
  dirplot map github://pallets/flask
225
+ dirplot map github://torvalds/linux@v6.12/Documentation
213
226
  dirplot map docker://my-container:/app
214
227
  dirplot map pod://my-pod:/app
215
228
  dirplot map pod://my-pod@staging:/app
@@ -234,6 +247,8 @@ To create a token: GitHub → Settings → Developer settings → Personal acces
234
247
 
235
248
  ## Python API
236
249
 
250
+ > **Note:** The programmatic Python API is still evolving and may change between releases without notice. Pin a specific version if you depend on it. The CLI interface is stable.
251
+
237
252
  The public API is small — `build_tree`, `create_treemap`, `create_treemap_svg`, and the display helpers:
238
253
 
239
254
  ```python
@@ -25,7 +25,9 @@
25
25
  - Save output to a PNG or SVG file with `--output`.
26
26
  - Exclude paths with `--exclude` (repeatable).
27
27
  - Works on macOS, Linux, and Windows; WSL2 fully supported.
28
- - Scan remote hosts over SSH (`pip install "dirplot[ssh]"`), AWS S3 buckets (`pip install "dirplot[s3]"`), any public/private GitHub repository, **running Docker containers**, or **Kubernetes pods** — all without extra dependencies beyond the respective CLI/SDK. See [EXAMPLES.md](docs/EXAMPLES.md).
28
+ - Scan remote hosts over SSH (`pip install "dirplot[ssh]"`), AWS S3 buckets (`pip install "dirplot[s3]"`), any public/private GitHub repository (including specific branch, tag, commit SHA, or subdirectory), **running Docker containers**, or **Kubernetes pods** — all without extra dependencies beyond the respective CLI/SDK. See [EXAMPLES.md](docs/EXAMPLES.md).
29
+ - Optional **file-count legend** (`--legend`) — a corner overlay listing the top extensions by number of files, with coloured swatches and counts, automatically sized to fit the image.
30
+ - **Wide archive support** — reads zip, tar (gz/bz2/xz/zst), 7z, rar, and via libarchive: iso, cpio, rpm, cab, lha/lzh, xar/pkg, a/ar, and all ZIP-based formats (jar, whl, apk, nupkg, vsix, ipa, …) as virtual directory trees without unpacking. Encrypted archives are handled gracefully: metadata-only reads work without a password for most formats; a password can be supplied with `--password` or entered interactively when needed.
29
31
 
30
32
  ## How It Works
31
33
 
@@ -92,6 +94,12 @@ dirplot map . --size 1920x1080 --output dirplot.png --no-show
92
94
  # Don't apply cushion shading — makes tiles look flat
93
95
  dirplot map . --no-cushion
94
96
 
97
+ # Show a file-count legend (top 20 extensions by default)
98
+ dirplot map . --legend
99
+
100
+ # Show a file-count legend limited to 10 entries
101
+ dirplot map . --legend 10
102
+
95
103
  # Save as an interactive SVG (hover highlight + floating tooltip)
96
104
  dirplot map . --output treemap.svg --no-show
97
105
 
@@ -107,7 +115,7 @@ dirplot map . --format svg --output treemap.svg --no-show
107
115
  | `--format` | `-f` | auto | Output format: `png` or `svg`. Auto-detected from `--output` extension |
108
116
  | `--show/--no-show` | | `--show` | Display the image after rendering |
109
117
  | `--inline` | | off | Display in terminal (protocol auto-detected; PNG only) |
110
- | `--legend/--no-legend` | | `--no-legend` | Show file-extension colour legend |
118
+ | `--legend [N]` | | off | Show file-count legend; `N` sets max entries (default: 20) |
111
119
  | `--font-size` | `-s` | `12` | Directory label font size in pixels |
112
120
  | `--colormap` | `-c` | `tab20` | Matplotlib colormap for unknown extensions |
113
121
  | `--exclude` | `-e` | — | Path to exclude (repeatable) |
@@ -115,6 +123,7 @@ dirplot map . --format svg --output treemap.svg --no-show
115
123
  | `--header/--no-header` | | `--header` | Print info lines before rendering |
116
124
  | `--cushion/--no-cushion` | | `--cushion` | Apply van Wijk cushion shading for a raised 3-D look |
117
125
  | `--log/--no-log` | | `--no-log` | Use log of file sizes for layout, making small files more visible |
126
+ | `--password` | | — | Password for encrypted archives; prompted interactively if not supplied and needed |
118
127
  | `--github-token` | | `$GITHUB_TOKEN` | GitHub personal access token for private repos or higher rate limits |
119
128
 
120
129
  ## Inline Display
@@ -140,7 +149,7 @@ The default mode (`--show`, no `--inline`) opens the PNG in the system viewer (`
140
149
 
141
150
  ## Archives
142
151
 
143
- dirplot can read local archive files (zip, tar, 7z, rar, and ZIP-based formats like jar, whl, apk) as treemap inputs without unpacking them. See [ARCHIVES.md](docs/ARCHIVES.md) for supported formats, dependencies, and RAR setup on macOS.
152
+ dirplot can read local archive files without unpacking them — zip, tar (gz/bz2/xz/zst), 7z, rar, and many more via libarchive (iso, cpio, rpm, cab, lha, xar, and all ZIP-based formats like jar, whl, apk, nupkg, vsix, ipa). See [ARCHIVES.md](docs/ARCHIVES.md) for the full list, dependencies, and platform notes.
144
153
 
145
154
  ```bash
146
155
  dirplot map project.zip
@@ -164,6 +173,7 @@ pip install "dirplot[s3]" # AWS S3 via boto3
164
173
  dirplot map ssh://alice@prod.example.com/var/www
165
174
  dirplot map s3://noaa-ghcn-pds --no-sign
166
175
  dirplot map github://pallets/flask
176
+ dirplot map github://torvalds/linux@v6.12/Documentation
167
177
  dirplot map docker://my-container:/app
168
178
  dirplot map pod://my-pod:/app
169
179
  dirplot map pod://my-pod@staging:/app
@@ -188,6 +198,8 @@ To create a token: GitHub → Settings → Developer settings → Personal acces
188
198
 
189
199
  ## Python API
190
200
 
201
+ > **Note:** The programmatic Python API is still evolving and may change between releases without notice. Pin a specific version if you depend on it. The CLI interface is stable.
202
+
191
203
  The public API is small — `build_tree`, `create_treemap`, `create_treemap_svg`, and the display helpers:
192
204
 
193
205
  ```python
@@ -4,7 +4,7 @@
4
4
 
5
5
  | Version | Supported |
6
6
  |---------|--------------------|
7
- | 0.1.x | :white_check_mark: |
7
+ | 0.3.x | :white_check_mark: |
8
8
 
9
9
  ## Reporting a Vulnerability
10
10
 
@@ -21,14 +21,34 @@ dirplot map backup.7z --exclude node_modules
21
21
  | `.apk` | ZIP (Android package) | `zipfile` (stdlib) |
22
22
  | `.epub` | ZIP (eBook) | `zipfile` (stdlib) |
23
23
  | `.xpi` | ZIP (browser extension) | `zipfile` (stdlib) |
24
+ | `.nupkg` | ZIP (NuGet package) | `zipfile` (stdlib) |
25
+ | `.vsix` | ZIP (VS Code extension) | `zipfile` (stdlib) |
26
+ | `.ipa` | ZIP (iOS app package) | `zipfile` (stdlib) |
27
+ | `.aab` | ZIP (Android App Bundle) | `zipfile` (stdlib) |
24
28
  | `.tar`, `.tar.gz`, `.tgz` | TAR | `tarfile` (stdlib) |
25
29
  | `.tar.bz2`, `.tbz2` | TAR | `tarfile` (stdlib) |
26
30
  | `.tar.xz`, `.txz` | TAR | `tarfile` (stdlib) |
27
31
  | `.7z` | 7-Zip | `py7zr` (bundled) |
28
32
  | `.rar` | RAR | `rarfile` (bundled) |
29
-
30
- ZIP and all its synonyms (`.jar`, `.whl`, etc.) are read with the same stdlib
31
- `zipfile` module the format is identical, only the extension differs.
33
+ | `.tar.zst`, `.tzst` | TAR + Zstandard | `libarchive-c` (bundled) |
34
+ | `.iso` | ISO 9660 disc image | `libarchive-c` (bundled) |
35
+ | `.cpio` | CPIO archive | `libarchive-c` (bundled) |
36
+ | `.xar` | XAR / macOS package | `libarchive-c` (bundled) |
37
+ | `.pkg` | macOS installer package (XAR) | `libarchive-c` (bundled) |
38
+ | `.dmg` | macOS disk image | `libarchive-c` (bundled) |
39
+ | `.img` | Raw/FAT disk image | `libarchive-c` (bundled) |
40
+ | `.rpm` | RPM package (Red Hat / Fedora / SUSE) | `libarchive-c` (bundled) |
41
+ | `.cab` | Microsoft Cabinet (Windows installers/drivers) | `libarchive-c` (bundled) |
42
+ | `.lha`, `.lzh` | LHA/LZH (legacy, common in Japanese software) | `libarchive-c` (bundled) |
43
+ | `.a`, `.ar` | Unix static library / generic `ar` archive | `libarchive-c` (bundled) |
44
+
45
+ ZIP and all its synonyms (`.jar`, `.whl`, `.nupkg`, etc.) are read with the
46
+ same stdlib `zipfile` module — the format is identical, only the extension
47
+ differs.
48
+
49
+ `.tar.zst` and `.tzst` are routed through libarchive rather than stdlib
50
+ `tarfile`, which only gained zstd support in Python 3.12. This ensures
51
+ consistent behaviour across all supported Python versions (3.10+).
32
52
 
33
53
  Symlinks inside TAR archives are silently skipped. Dotfiles (members whose
34
54
  filename starts with `.`) are skipped in all formats, consistent with the
@@ -36,13 +56,33 @@ behaviour of local and remote directory scans.
36
56
 
37
57
  ## Python dependencies
38
58
 
39
- `py7zr` and `rarfile` are regular dependencies — no extra install flag is
40
- needed:
59
+ `py7zr`, `rarfile`, and `libarchive-c` are regular dependencies — no extra
60
+ install flag is needed:
61
+
62
+ ```bash
63
+ pip install dirplot # py7zr, rarfile, and libarchive-c included
64
+ ```
65
+
66
+ `libarchive-c` is a thin Python binding to the system **libarchive** C
67
+ library. The library itself must be installed separately:
41
68
 
42
69
  ```bash
43
- pip install dirplot # py7zr and rarfile included
70
+ # macOS
71
+ brew install libarchive
72
+
73
+ # Debian / Ubuntu
74
+ sudo apt install libarchive-dev
75
+
76
+ # Fedora / RHEL
77
+ sudo dnf install libarchive-devel
44
78
  ```
45
79
 
80
+ On macOS the Homebrew-installed libarchive includes support for reading Apple
81
+ disk images (`.dmg`), ISO 9660 (`.iso`), XAR/PKG (`.xar`, `.pkg`), CPIO
82
+ (`.cpio`), and raw disk images (`.img`). Support for individual formats may
83
+ vary across Linux distributions depending on how their libarchive package was
84
+ compiled.
85
+
46
86
  ## RAR: system tool requirement
47
87
 
48
88
  `rarfile` reads RAR metadata in pure Python, but the `rar` CLI must be
@@ -96,6 +136,25 @@ The pytest `sample_archives` session fixture in `tests/conftest.py` regenerates
96
136
  the same files into a temporary directory at test-session start, so running the
97
137
  script is not required for CI or for running the test suite locally.
98
138
 
139
+ ## Intentionally unsupported formats
140
+
141
+ **`.deb` (Debian/Ubuntu packages)** — a `.deb` file is an `ar` archive whose
142
+ members are `debian-binary`, `control.tar.*`, and `data.tar.*`. libarchive
143
+ sees only those three `ar` members, not the actual file tree inside
144
+ `data.tar.*`. Showing three opaque tarball blobs is not useful, so `.deb` is
145
+ not registered as a supported input. To inspect the contents, extract the
146
+ `data.tar.*` member first:
147
+
148
+ ```bash
149
+ ar x package.deb data.tar.gz
150
+ dirplot map data.tar.gz
151
+ ```
152
+
153
+ **macOS UDIF disk images (`.dmg`)** — most modern macOS disk images use the
154
+ proprietary UDIF format, which is not supported by the open-source libarchive.
155
+ dirplot will report a clear error if the format is unrecognised. Plain
156
+ HFS+/FAT images without UDIF wrapping may still be readable.
157
+
99
158
  ## Behaviour notes
100
159
 
101
160
  - **Root name**: the archive filename without its suffix is used as the root
@@ -64,6 +64,8 @@ dirplot map ssh://prod/var/www # resolves using the config block above
64
64
 
65
65
  ### Python API
66
66
 
67
+ > **Note:** The programmatic Python API is still evolving and may change between releases without notice. Pin a specific version if you depend on it. The CLI interface is stable.
68
+
67
69
  ```python
68
70
  from dirplot.ssh import connect, build_tree_ssh
69
71
  from dirplot.render import create_treemap
@@ -126,6 +128,8 @@ boto3's standard credential chain is used automatically — no extra configurati
126
128
 
127
129
  ### Python API
128
130
 
131
+ > **Note:** The programmatic Python API is still evolving and may change between releases without notice. Pin a specific version if you depend on it. The CLI interface is stable.
132
+
129
133
  ```python
130
134
  from dirplot.s3 import make_s3_client, build_tree_s3
131
135
  from dirplot.render import create_treemap
@@ -225,6 +229,8 @@ Tokens are resolved in this order:
225
229
 
226
230
  ### Python API
227
231
 
232
+ > **Note:** The programmatic Python API is still evolving and may change between releases without notice. Pin a specific version if you depend on it. The CLI interface is stable.
233
+
228
234
  ```python
229
235
  from dirplot.github import build_tree_github
230
236
  from dirplot.render import create_treemap
@@ -294,6 +300,8 @@ docker rm -f pg-demo
294
300
 
295
301
  ### Python API
296
302
 
303
+ > **Note:** The programmatic Python API is still evolving and may change between releases without notice. Pin a specific version if you depend on it. The CLI interface is stable.
304
+
297
305
  ```python
298
306
  from dirplot.docker import build_tree_docker
299
307
  from dirplot.render import create_treemap
@@ -370,6 +378,8 @@ kubectl delete pod pg-demo --grace-period=0
370
378
 
371
379
  ### Python API
372
380
 
381
+ > **Note:** The programmatic Python API is still evolving and may change between releases without notice. Pin a specific version if you depend on it. The CLI interface is stable.
382
+
373
383
  ```python
374
384
  from dirplot.k8s import build_tree_pod
375
385
  from dirplot.render import create_treemap
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "dirplot"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "Static treemap bitmaps for directory trees and archives, displayed as inline terminal images"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -32,6 +32,7 @@ classifiers = [
32
32
  ]
33
33
  dependencies = [
34
34
  "drawsvg>=2.4.1",
35
+ "libarchive-c>=5.0",
35
36
  "matplotlib>=3.7",
36
37
  "pillow>=9.0",
37
38
  "py7zr>=0.20",
@@ -53,6 +54,9 @@ dev = [
53
54
  "ruff>=0.4",
54
55
  "pre-commit>=3.0",
55
56
  ]
57
+ libarchive = [
58
+ "libarchive-c>=5.3",
59
+ ]
56
60
 
57
61
  [project.urls]
58
62
  Repository = "https://github.com/deeplook/dirplot"
@@ -90,7 +94,7 @@ python_version = "3.10"
90
94
  strict = true
91
95
 
92
96
  [[tool.mypy.overrides]]
93
- module = ["matplotlib.*", "squarify", "PIL.*", "paramiko.*", "boto3.*", "botocore.*", "py7zr.*", "rarfile", "drawsvg.*"]
97
+ module = ["matplotlib.*", "squarify", "PIL.*", "paramiko.*", "boto3.*", "botocore.*", "py7zr.*", "rarfile", "drawsvg.*", "libarchive.*"]
94
98
  ignore_missing_imports = true
95
99
 
96
100
  # ---------------------------------------------------------------------------