treex-cli 0.1.6__tar.gz → 0.1.8__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.
- {treex_cli-0.1.6/treex_cli.egg-info → treex_cli-0.1.8}/PKG-INFO +4 -3
- {treex_cli-0.1.6 → treex_cli-0.1.8}/README.md +3 -2
- {treex_cli-0.1.6 → treex_cli-0.1.8}/pyproject.toml +3 -2
- {treex_cli-0.1.6 → treex_cli-0.1.8}/treex.py +83 -52
- {treex_cli-0.1.6 → treex_cli-0.1.8/treex_cli.egg-info}/PKG-INFO +4 -3
- {treex_cli-0.1.6 → treex_cli-0.1.8}/LICENSE +0 -0
- {treex_cli-0.1.6 → treex_cli-0.1.8}/setup.cfg +0 -0
- {treex_cli-0.1.6 → treex_cli-0.1.8}/treex_cli.egg-info/SOURCES.txt +0 -0
- {treex_cli-0.1.6 → treex_cli-0.1.8}/treex_cli.egg-info/dependency_links.txt +0 -0
- {treex_cli-0.1.6 → treex_cli-0.1.8}/treex_cli.egg-info/entry_points.txt +0 -0
- {treex_cli-0.1.6 → treex_cli-0.1.8}/treex_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: treex-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: List directory contents as a tree with file and directory metadata
|
|
5
5
|
Author: Corey Goldberg
|
|
6
6
|
Maintainer: Corey Goldberg
|
|
@@ -100,7 +100,7 @@ Install `treex` from [PyPI][pypi-home] using either `pip` or `pipx`:
|
|
|
100
100
|
|
|
101
101
|
```
|
|
102
102
|
$ treex --help
|
|
103
|
-
usage: treex [-h] [-a] [-m] [-q] [-s] [directory]
|
|
103
|
+
usage: treex [-h] [-a] [-m] [-q] [-d] [-s] [directory]
|
|
104
104
|
|
|
105
105
|
List directory contents as a tree with file and directory metadata.
|
|
106
106
|
|
|
@@ -109,9 +109,10 @@ positional arguments:
|
|
|
109
109
|
|
|
110
110
|
options:
|
|
111
111
|
-h, --help show this help message and exit
|
|
112
|
-
-a, --all show all files
|
|
112
|
+
-a, --all show all files, including those ignored by Git
|
|
113
113
|
-m, --modified show file modification times
|
|
114
114
|
-q, --quiet don't show file metadata
|
|
115
|
+
-d, --dirs show directories only
|
|
115
116
|
-s, --summary show summary only
|
|
116
117
|
```
|
|
117
118
|
|
|
@@ -75,7 +75,7 @@ Install `treex` from [PyPI][pypi-home] using either `pip` or `pipx`:
|
|
|
75
75
|
|
|
76
76
|
```
|
|
77
77
|
$ treex --help
|
|
78
|
-
usage: treex [-h] [-a] [-m] [-q] [-s] [directory]
|
|
78
|
+
usage: treex [-h] [-a] [-m] [-q] [-d] [-s] [directory]
|
|
79
79
|
|
|
80
80
|
List directory contents as a tree with file and directory metadata.
|
|
81
81
|
|
|
@@ -84,9 +84,10 @@ positional arguments:
|
|
|
84
84
|
|
|
85
85
|
options:
|
|
86
86
|
-h, --help show this help message and exit
|
|
87
|
-
-a, --all show all files
|
|
87
|
+
-a, --all show all files, including those ignored by Git
|
|
88
88
|
-m, --modified show file modification times
|
|
89
89
|
-q, --quiet don't show file metadata
|
|
90
|
+
-d, --dirs show directories only
|
|
90
91
|
-s, --summary show summary only
|
|
91
92
|
```
|
|
92
93
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "treex-cli"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.8"
|
|
8
8
|
description="List directory contents as a tree with file and directory metadata"
|
|
9
9
|
license = "MIT"
|
|
10
10
|
license-files = ["LICENSE"]
|
|
@@ -53,6 +53,7 @@ py-modules = ["treex"]
|
|
|
53
53
|
[tool.pytest]
|
|
54
54
|
addopts = ["-v"]
|
|
55
55
|
filterwarnings = ["default"]
|
|
56
|
+
tmp_path_retention_policy = "none"
|
|
56
57
|
|
|
57
58
|
[tool.ruff]
|
|
58
59
|
line-length = 88
|
|
@@ -62,7 +63,7 @@ target-version = "py310"
|
|
|
62
63
|
[tool.ruff.lint]
|
|
63
64
|
select = ["ALL"]
|
|
64
65
|
ignore = [
|
|
65
|
-
"ANN", "COM812", "D", "DTZ001", "DTZ006",
|
|
66
|
+
"ANN", "C901", "COM812", "D", "DTZ001", "DTZ006",
|
|
66
67
|
"FBT", "PLR", "S603", "S607", "T201"
|
|
67
68
|
]
|
|
68
69
|
fixable = ["ALL"]
|
|
@@ -14,6 +14,7 @@ filesystem is scanned normally without Git filtering.
|
|
|
14
14
|
|
|
15
15
|
import argparse
|
|
16
16
|
import subprocess
|
|
17
|
+
import sys
|
|
17
18
|
from contextlib import suppress
|
|
18
19
|
from datetime import datetime
|
|
19
20
|
from pathlib import Path
|
|
@@ -151,6 +152,7 @@ def _collect_tree(
|
|
|
151
152
|
rows,
|
|
152
153
|
show_metadata,
|
|
153
154
|
show_modified,
|
|
155
|
+
show_files,
|
|
154
156
|
):
|
|
155
157
|
"""Walk the tree once and collect the output rows."""
|
|
156
158
|
entries = _get_tree_entries(path, gitignore)
|
|
@@ -158,15 +160,26 @@ def _collect_tree(
|
|
|
158
160
|
rows.append((prefix + "└── [permission denied]", None))
|
|
159
161
|
return 0
|
|
160
162
|
total_size = 0
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
# When files are hidden, only directories determine which visible
|
|
164
|
+
# entry is last. Files are still processed for stats and sizes.
|
|
165
|
+
visible_entries = entries
|
|
166
|
+
if not show_files:
|
|
167
|
+
visible_entries = [entry for entry in entries if entry.is_dir()]
|
|
168
|
+
visible_index = 0
|
|
169
|
+
for entry in entries:
|
|
170
|
+
is_visible = show_files or entry.is_dir()
|
|
171
|
+
if is_visible:
|
|
172
|
+
is_last = visible_index == len(visible_entries) - 1
|
|
173
|
+
visible_index += 1
|
|
174
|
+
connector = "└── " if is_last else "├── "
|
|
175
|
+
tree_name = prefix + connector + entry.name
|
|
176
|
+
else:
|
|
177
|
+
tree_name = None
|
|
165
178
|
if entry.is_dir():
|
|
166
179
|
stats["directories"] += 1
|
|
167
180
|
row_index = len(rows)
|
|
168
181
|
rows.append((tree_name, None))
|
|
169
|
-
# Indent nested entries, preserving the tree's vertical branch
|
|
182
|
+
# Indent nested entries, preserving the tree's vertical branch.
|
|
170
183
|
extension = " " if is_last else "│ "
|
|
171
184
|
dir_size = _collect_tree(
|
|
172
185
|
entry,
|
|
@@ -176,6 +189,7 @@ def _collect_tree(
|
|
|
176
189
|
rows,
|
|
177
190
|
show_metadata,
|
|
178
191
|
show_modified,
|
|
192
|
+
show_files,
|
|
179
193
|
)
|
|
180
194
|
total_size += dir_size
|
|
181
195
|
if show_metadata:
|
|
@@ -186,25 +200,17 @@ def _collect_tree(
|
|
|
186
200
|
stats["files"] += 1
|
|
187
201
|
stats["total_size"] += size
|
|
188
202
|
total_size += size
|
|
189
|
-
|
|
190
|
-
|
|
203
|
+
if show_files:
|
|
204
|
+
timestamp = modified if show_modified else None
|
|
205
|
+
rows.append((tree_name, (size_text, info, timestamp)))
|
|
191
206
|
else:
|
|
192
207
|
stats["files"] += 1
|
|
193
208
|
stats["total_size"] = None
|
|
194
|
-
|
|
209
|
+
if show_files:
|
|
210
|
+
rows.append((tree_name, None))
|
|
195
211
|
return total_size
|
|
196
212
|
|
|
197
213
|
|
|
198
|
-
def print_summary(stats):
|
|
199
|
-
directories = stats["directories"]
|
|
200
|
-
files = stats["files"]
|
|
201
|
-
total_size = stats["total_size"]
|
|
202
|
-
summary = f"{directories:,} directories • {files:,} files"
|
|
203
|
-
if total_size:
|
|
204
|
-
summary += f" • {_format_size(total_size)}"
|
|
205
|
-
print(summary)
|
|
206
|
-
|
|
207
|
-
|
|
208
214
|
def print_tree(
|
|
209
215
|
directory,
|
|
210
216
|
prefix="",
|
|
@@ -213,8 +219,9 @@ def print_tree(
|
|
|
213
219
|
show_metadata=True,
|
|
214
220
|
show_modified=False,
|
|
215
221
|
show_tree=True,
|
|
222
|
+
show_files=True,
|
|
216
223
|
):
|
|
217
|
-
"""Print the directory tree with aligned
|
|
224
|
+
"""Print the directory tree with aligned metadata."""
|
|
218
225
|
if stats is None:
|
|
219
226
|
stats = {"directories": 0, "files": 0, "total_size": 0}
|
|
220
227
|
rows = []
|
|
@@ -227,18 +234,16 @@ def print_tree(
|
|
|
227
234
|
rows,
|
|
228
235
|
show_metadata,
|
|
229
236
|
show_modified,
|
|
237
|
+
show_files,
|
|
230
238
|
)
|
|
231
239
|
if show_tree:
|
|
232
|
-
# Align
|
|
233
|
-
max_tree_name_width = max(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
237
|
-
for tree_name, file_info_data in rows:
|
|
238
|
-
if file_info_data is None:
|
|
240
|
+
# Align metadata with the longest tree/name
|
|
241
|
+
max_tree_name_width = max((len(tree_name) for tree_name, _ in rows), default=0)
|
|
242
|
+
for tree_name, metadata in rows:
|
|
243
|
+
if metadata is None:
|
|
239
244
|
print(tree_name)
|
|
240
245
|
continue
|
|
241
|
-
size_text, info, modified =
|
|
246
|
+
size_text, info, modified = metadata
|
|
242
247
|
output = f"{tree_name:<{max_tree_name_width}}{size_text:>10}"
|
|
243
248
|
if info is not None:
|
|
244
249
|
output += f" {info:<10}"
|
|
@@ -248,11 +253,24 @@ def print_tree(
|
|
|
248
253
|
return stats
|
|
249
254
|
|
|
250
255
|
|
|
256
|
+
def print_summary(stats):
|
|
257
|
+
"""Print a summary of directory/file counts and total size."""
|
|
258
|
+
directories = stats["directories"]
|
|
259
|
+
files = stats["files"]
|
|
260
|
+
total_size = stats["total_size"]
|
|
261
|
+
directory_label = "directory" if directories == 1 else "directories"
|
|
262
|
+
file_label = "file" if files == 1 else "files"
|
|
263
|
+
summary = f"{directories:,} {directory_label} • {files:,} {file_label}"
|
|
264
|
+
if total_size is not None:
|
|
265
|
+
summary += f" • {_format_size(total_size)}"
|
|
266
|
+
print(summary)
|
|
267
|
+
|
|
268
|
+
|
|
251
269
|
def parse_args(argv=None):
|
|
252
270
|
"""Parse command-line arguments."""
|
|
253
271
|
parser = argparse.ArgumentParser(
|
|
254
|
-
description="List directory contents as a tree
|
|
255
|
-
"file and directory metadata.",
|
|
272
|
+
description="List directory contents as a tree "
|
|
273
|
+
"with file and directory metadata.",
|
|
256
274
|
)
|
|
257
275
|
parser.add_argument(
|
|
258
276
|
"directory",
|
|
@@ -265,7 +283,7 @@ def parse_args(argv=None):
|
|
|
265
283
|
"-a",
|
|
266
284
|
"--all",
|
|
267
285
|
action="store_true",
|
|
268
|
-
help="show all files
|
|
286
|
+
help="show all files, including those ignored by Git",
|
|
269
287
|
)
|
|
270
288
|
parser.add_argument(
|
|
271
289
|
"-m",
|
|
@@ -279,6 +297,12 @@ def parse_args(argv=None):
|
|
|
279
297
|
action="store_true",
|
|
280
298
|
help="don't show file metadata",
|
|
281
299
|
)
|
|
300
|
+
parser.add_argument(
|
|
301
|
+
"-d",
|
|
302
|
+
"--dirs",
|
|
303
|
+
action="store_true",
|
|
304
|
+
help="show directories only",
|
|
305
|
+
)
|
|
282
306
|
parser.add_argument(
|
|
283
307
|
"-s",
|
|
284
308
|
"--summary",
|
|
@@ -289,28 +313,35 @@ def parse_args(argv=None):
|
|
|
289
313
|
|
|
290
314
|
|
|
291
315
|
def main():
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
316
|
+
try:
|
|
317
|
+
args = parse_args()
|
|
318
|
+
path = args.directory
|
|
319
|
+
if not path.is_dir():
|
|
320
|
+
print(f"Not a directory: {path}", file=sys.stderr)
|
|
321
|
+
return 1
|
|
322
|
+
# Only initialize Git support if it will be used
|
|
323
|
+
gitignore = None if args.all else GitIgnore(path)
|
|
324
|
+
show_tree = not args.summary
|
|
325
|
+
show_metadata = not args.quiet
|
|
326
|
+
show_files = not args.dirs
|
|
327
|
+
if show_tree:
|
|
328
|
+
print(path)
|
|
329
|
+
stats = print_tree(
|
|
330
|
+
path,
|
|
331
|
+
gitignore=gitignore,
|
|
332
|
+
show_metadata=show_metadata,
|
|
333
|
+
show_modified=args.modified,
|
|
334
|
+
show_tree=show_tree,
|
|
335
|
+
show_files=show_files,
|
|
336
|
+
)
|
|
337
|
+
if show_tree:
|
|
338
|
+
print()
|
|
339
|
+
print_summary(stats)
|
|
340
|
+
except KeyboardInterrupt:
|
|
341
|
+
print("\nInterrupted", file=sys.stderr)
|
|
342
|
+
return 130
|
|
343
|
+
else:
|
|
344
|
+
return 0
|
|
314
345
|
|
|
315
346
|
|
|
316
347
|
if __name__ == "__main__":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: treex-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: List directory contents as a tree with file and directory metadata
|
|
5
5
|
Author: Corey Goldberg
|
|
6
6
|
Maintainer: Corey Goldberg
|
|
@@ -100,7 +100,7 @@ Install `treex` from [PyPI][pypi-home] using either `pip` or `pipx`:
|
|
|
100
100
|
|
|
101
101
|
```
|
|
102
102
|
$ treex --help
|
|
103
|
-
usage: treex [-h] [-a] [-m] [-q] [-s] [directory]
|
|
103
|
+
usage: treex [-h] [-a] [-m] [-q] [-d] [-s] [directory]
|
|
104
104
|
|
|
105
105
|
List directory contents as a tree with file and directory metadata.
|
|
106
106
|
|
|
@@ -109,9 +109,10 @@ positional arguments:
|
|
|
109
109
|
|
|
110
110
|
options:
|
|
111
111
|
-h, --help show this help message and exit
|
|
112
|
-
-a, --all show all files
|
|
112
|
+
-a, --all show all files, including those ignored by Git
|
|
113
113
|
-m, --modified show file modification times
|
|
114
114
|
-q, --quiet don't show file metadata
|
|
115
|
+
-d, --dirs show directories only
|
|
115
116
|
-s, --summary show summary only
|
|
116
117
|
```
|
|
117
118
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|