python-du 0.1.0__tar.gz → 0.1.2__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.
- python_du-0.1.2/PKG-INFO +88 -0
- python_du-0.1.2/README.md +81 -0
- {python_du-0.1.0 → python_du-0.1.2}/pyproject.toml +5 -1
- {python_du-0.1.0 → python_du-0.1.2}/python_du/renderer.py +12 -8
- {python_du-0.1.0 → python_du-0.1.2}/python_du/scanner.py +9 -2
- python_du-0.1.2/python_du.egg-info/PKG-INFO +88 -0
- python_du-0.1.0/PKG-INFO +0 -5
- python_du-0.1.0/README.md +0 -97
- python_du-0.1.0/python_du.egg-info/PKG-INFO +0 -5
- {python_du-0.1.0 → python_du-0.1.2}/python_du/__init__.py +0 -0
- {python_du-0.1.0 → python_du-0.1.2}/python_du/cli.py +0 -0
- {python_du-0.1.0 → python_du-0.1.2}/python_du.egg-info/SOURCES.txt +0 -0
- {python_du-0.1.0 → python_du-0.1.2}/python_du.egg-info/dependency_links.txt +0 -0
- {python_du-0.1.0 → python_du-0.1.2}/python_du.egg-info/entry_points.txt +0 -0
- {python_du-0.1.0 → python_du-0.1.2}/python_du.egg-info/top_level.txt +0 -0
- {python_du-0.1.0 → python_du-0.1.2}/setup.cfg +0 -0
python_du-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-du
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: A disk usage analyzer that prints a visual map of folder sizes
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
|
|
8
|
+
# python-du
|
|
9
|
+
|
|
10
|
+
A disk usage analyzer that scans a directory and prints a visual tree map of folder sizes — right in your terminal.
|
|
11
|
+
|
|
12
|
+
## Example
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install -e .
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
pip uninstall python-du
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python-du [path] [options]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If no path is given, the current directory is scanned.
|
|
33
|
+
|
|
34
|
+
### Options
|
|
35
|
+
|
|
36
|
+
| Flag | Description |
|
|
37
|
+
|------|-------------|
|
|
38
|
+
| `-d`, `--max-depth N` | Maximum tree depth to display (default: 4) |
|
|
39
|
+
| `-m`, `--min-percent N` | Hide entries smaller than N% of total (default: 0.5) |
|
|
40
|
+
| `--no-color` | Disable colored output |
|
|
41
|
+
| `--sort-alpha` | Sort alphabetically instead of by size |
|
|
42
|
+
| `--scan-depth N` | Limit how deep the filesystem scan goes (default: unlimited) |
|
|
43
|
+
| `-L`, `--follow-symlinks` | Follow symbolic links |
|
|
44
|
+
|
|
45
|
+
### Examples
|
|
46
|
+
|
|
47
|
+
Scan the current directory with defaults:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python-du
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Scan `/var/log` showing only entries above 5%, two levels deep:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python-du /var/log -d 2 -m 5
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Pipe to a file (automatically disables color):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python-du /home > usage-report.txt
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Publishing to PyPI
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
pip install build twine
|
|
69
|
+
python -m build
|
|
70
|
+
twine upload dist/*
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
When prompted, use `__token__` as the username and your PyPI API token as the password.
|
|
74
|
+
|
|
75
|
+
To skip the prompt, create a `~/.pypirc` file:
|
|
76
|
+
|
|
77
|
+
```ini
|
|
78
|
+
[pypi]
|
|
79
|
+
username = __token__
|
|
80
|
+
password = pypi-YOUR-TOKEN-HERE
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> **Note:** Bump the `version` in `pyproject.toml` before each upload — PyPI rejects duplicate version numbers.
|
|
84
|
+
|
|
85
|
+
## Requirements
|
|
86
|
+
|
|
87
|
+
- Python >= 3.9
|
|
88
|
+
- No external dependencies
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# python-du
|
|
2
|
+
|
|
3
|
+
A disk usage analyzer that scans a directory and prints a visual tree map of folder sizes — right in your terminal.
|
|
4
|
+
|
|
5
|
+
## Example
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install -e .
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
pip uninstall python-du
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
python-du [path] [options]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If no path is given, the current directory is scanned.
|
|
26
|
+
|
|
27
|
+
### Options
|
|
28
|
+
|
|
29
|
+
| Flag | Description |
|
|
30
|
+
|------|-------------|
|
|
31
|
+
| `-d`, `--max-depth N` | Maximum tree depth to display (default: 4) |
|
|
32
|
+
| `-m`, `--min-percent N` | Hide entries smaller than N% of total (default: 0.5) |
|
|
33
|
+
| `--no-color` | Disable colored output |
|
|
34
|
+
| `--sort-alpha` | Sort alphabetically instead of by size |
|
|
35
|
+
| `--scan-depth N` | Limit how deep the filesystem scan goes (default: unlimited) |
|
|
36
|
+
| `-L`, `--follow-symlinks` | Follow symbolic links |
|
|
37
|
+
|
|
38
|
+
### Examples
|
|
39
|
+
|
|
40
|
+
Scan the current directory with defaults:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
python-du
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Scan `/var/log` showing only entries above 5%, two levels deep:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python-du /var/log -d 2 -m 5
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Pipe to a file (automatically disables color):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
python-du /home > usage-report.txt
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Publishing to PyPI
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
pip install build twine
|
|
62
|
+
python -m build
|
|
63
|
+
twine upload dist/*
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
When prompted, use `__token__` as the username and your PyPI API token as the password.
|
|
67
|
+
|
|
68
|
+
To skip the prompt, create a `~/.pypirc` file:
|
|
69
|
+
|
|
70
|
+
```ini
|
|
71
|
+
[pypi]
|
|
72
|
+
username = __token__
|
|
73
|
+
password = pypi-YOUR-TOKEN-HERE
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
> **Note:** Bump the `version` in `pyproject.toml` before each upload — PyPI rejects duplicate version numbers.
|
|
77
|
+
|
|
78
|
+
## Requirements
|
|
79
|
+
|
|
80
|
+
- Python >= 3.9
|
|
81
|
+
- No external dependencies
|
|
@@ -4,9 +4,13 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-du"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "A disk usage analyzer that prints a visual map of folder sizes"
|
|
9
|
+
readme = "README.md"
|
|
9
10
|
requires-python = ">=3.9"
|
|
10
11
|
|
|
12
|
+
[tool.setuptools.packages.find]
|
|
13
|
+
include = ["python_du*"]
|
|
14
|
+
|
|
11
15
|
[project.scripts]
|
|
12
16
|
python-du = "python_du.cli:main"
|
|
@@ -54,12 +54,13 @@ def render_tree(root: DirNode, config: RenderConfig | None = None) -> str:
|
|
|
54
54
|
lines: list[str] = []
|
|
55
55
|
|
|
56
56
|
total = root.total_size or 1
|
|
57
|
+
label_col = (cfg.max_depth + 1) * 4 + 24
|
|
57
58
|
|
|
58
59
|
header = f"{BOLD}{root.name}{RESET}" if cfg.use_color else root.name
|
|
59
60
|
lines.append(f"{header} [{format_size(root.total_size)}]")
|
|
60
61
|
lines.append("")
|
|
61
62
|
|
|
62
|
-
_render_node(root, lines, cfg, bar_width, total, prefix="", depth=0, color_idx=0)
|
|
63
|
+
_render_node(root, lines, cfg, bar_width, total, prefix="", depth=0, color_idx=0, label_col=label_col)
|
|
63
64
|
|
|
64
65
|
lines.append("")
|
|
65
66
|
lines.append(_summary_line(root, cfg))
|
|
@@ -75,24 +76,25 @@ def _render_node(
|
|
|
75
76
|
prefix: str,
|
|
76
77
|
depth: int,
|
|
77
78
|
color_idx: int,
|
|
79
|
+
label_col: int,
|
|
78
80
|
) -> None:
|
|
79
81
|
children = node.children
|
|
80
82
|
if cfg.sort_by_size:
|
|
81
83
|
children = sorted(children, key=lambda c: c.total_size, reverse=True)
|
|
82
84
|
|
|
83
85
|
own_files_size = node.own_size
|
|
84
|
-
entries: list[tuple[str, int, DirNode | None]] = []
|
|
86
|
+
entries: list[tuple[str, int, int, DirNode | None]] = []
|
|
85
87
|
for child in children:
|
|
86
88
|
pct = (child.total_size / root_total * 100) if root_total else 0
|
|
87
89
|
if pct >= cfg.min_percent or depth < 1:
|
|
88
|
-
entries.append((child.name, child.total_size, child))
|
|
90
|
+
entries.append((child.name, child.total_size, _count_files(child), child))
|
|
89
91
|
|
|
90
92
|
if own_files_size > 0:
|
|
91
93
|
pct = (own_files_size / root_total * 100) if root_total else 0
|
|
92
94
|
if pct >= cfg.min_percent or depth < 1:
|
|
93
|
-
entries.append(("<files>", own_files_size, None))
|
|
95
|
+
entries.append(("<files>", own_files_size, node.file_count, None))
|
|
94
96
|
|
|
95
|
-
for i, (name, size, child_node) in enumerate(entries):
|
|
97
|
+
for i, (name, size, fcount, child_node) in enumerate(entries):
|
|
96
98
|
is_last = i == len(entries) - 1
|
|
97
99
|
connector = TREE_BEND if is_last else TREE_TEE
|
|
98
100
|
child_prefix = TREE_BLANK if is_last else TREE_PIPE
|
|
@@ -102,15 +104,16 @@ def _render_node(
|
|
|
102
104
|
|
|
103
105
|
size_str = format_size(size)
|
|
104
106
|
pct_str = f" ({pct:5.1f}%)" if cfg.show_percent else ""
|
|
107
|
+
files_str = f" [{fcount:,} {'file' if fcount == 1 else 'files'}]" if fcount else ""
|
|
105
108
|
|
|
106
109
|
if cfg.use_color and child_node is None:
|
|
107
110
|
name_str = f"{DIM}{name}{RESET}"
|
|
108
|
-
elif cfg.use_color:
|
|
109
|
-
name_str = name
|
|
110
111
|
else:
|
|
111
112
|
name_str = name
|
|
112
113
|
|
|
113
|
-
|
|
114
|
+
visible_len = len(prefix) + len(connector) + len(name)
|
|
115
|
+
padding = max(1, label_col - visible_len)
|
|
116
|
+
lines.append(f"{prefix}{connector}{name_str}{' ' * padding}{size_str:>10s}{pct_str} {bar}{files_str}")
|
|
114
117
|
|
|
115
118
|
if child_node and depth < cfg.max_depth:
|
|
116
119
|
_render_node(
|
|
@@ -122,6 +125,7 @@ def _render_node(
|
|
|
122
125
|
prefix=prefix + child_prefix,
|
|
123
126
|
depth=depth + 1,
|
|
124
127
|
color_idx=color_idx + i,
|
|
128
|
+
label_col=label_col,
|
|
125
129
|
)
|
|
126
130
|
|
|
127
131
|
|
|
@@ -21,6 +21,11 @@ class DirNode:
|
|
|
21
21
|
return self.path.name or str(self.path)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
def _allocated_size(stat_result: os.stat_result) -> int:
|
|
25
|
+
blocks = getattr(stat_result, "st_blocks", None)
|
|
26
|
+
return stat_result.st_size if blocks is None else blocks * 512
|
|
27
|
+
|
|
28
|
+
|
|
24
29
|
def scan(root: Path, *, max_depth: int | None = None, follow_symlinks: bool = False) -> DirNode:
|
|
25
30
|
"""Walk *root* and return a tree of DirNode objects with computed sizes."""
|
|
26
31
|
return _scan_dir(root.resolve(), depth=0, max_depth=max_depth, follow_symlinks=follow_symlinks)
|
|
@@ -51,7 +56,8 @@ def _scan_dir(
|
|
|
51
56
|
|
|
52
57
|
if entry.is_file(follow_symlinks=follow_symlinks):
|
|
53
58
|
try:
|
|
54
|
-
|
|
59
|
+
stat_result = entry.stat(follow_symlinks=follow_symlinks)
|
|
60
|
+
node.own_size += _allocated_size(stat_result)
|
|
55
61
|
node.file_count += 1
|
|
56
62
|
except OSError:
|
|
57
63
|
pass
|
|
@@ -83,7 +89,8 @@ def _shallow_size(path: Path) -> DirNode:
|
|
|
83
89
|
for dirpath, _dirnames, filenames in os.walk(path):
|
|
84
90
|
for fname in filenames:
|
|
85
91
|
try:
|
|
86
|
-
|
|
92
|
+
stat_result = os.stat(os.path.join(dirpath, fname))
|
|
93
|
+
total += _allocated_size(stat_result)
|
|
87
94
|
fcount += 1
|
|
88
95
|
except OSError:
|
|
89
96
|
pass
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-du
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: A disk usage analyzer that prints a visual map of folder sizes
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
|
|
8
|
+
# python-du
|
|
9
|
+
|
|
10
|
+
A disk usage analyzer that scans a directory and prints a visual tree map of folder sizes — right in your terminal.
|
|
11
|
+
|
|
12
|
+
## Example
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install -e .
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
pip uninstall python-du
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python-du [path] [options]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If no path is given, the current directory is scanned.
|
|
33
|
+
|
|
34
|
+
### Options
|
|
35
|
+
|
|
36
|
+
| Flag | Description |
|
|
37
|
+
|------|-------------|
|
|
38
|
+
| `-d`, `--max-depth N` | Maximum tree depth to display (default: 4) |
|
|
39
|
+
| `-m`, `--min-percent N` | Hide entries smaller than N% of total (default: 0.5) |
|
|
40
|
+
| `--no-color` | Disable colored output |
|
|
41
|
+
| `--sort-alpha` | Sort alphabetically instead of by size |
|
|
42
|
+
| `--scan-depth N` | Limit how deep the filesystem scan goes (default: unlimited) |
|
|
43
|
+
| `-L`, `--follow-symlinks` | Follow symbolic links |
|
|
44
|
+
|
|
45
|
+
### Examples
|
|
46
|
+
|
|
47
|
+
Scan the current directory with defaults:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python-du
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Scan `/var/log` showing only entries above 5%, two levels deep:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python-du /var/log -d 2 -m 5
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Pipe to a file (automatically disables color):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python-du /home > usage-report.txt
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Publishing to PyPI
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
pip install build twine
|
|
69
|
+
python -m build
|
|
70
|
+
twine upload dist/*
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
When prompted, use `__token__` as the username and your PyPI API token as the password.
|
|
74
|
+
|
|
75
|
+
To skip the prompt, create a `~/.pypirc` file:
|
|
76
|
+
|
|
77
|
+
```ini
|
|
78
|
+
[pypi]
|
|
79
|
+
username = __token__
|
|
80
|
+
password = pypi-YOUR-TOKEN-HERE
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> **Note:** Bump the `version` in `pyproject.toml` before each upload — PyPI rejects duplicate version numbers.
|
|
84
|
+
|
|
85
|
+
## Requirements
|
|
86
|
+
|
|
87
|
+
- Python >= 3.9
|
|
88
|
+
- No external dependencies
|
python_du-0.1.0/PKG-INFO
DELETED
python_du-0.1.0/README.md
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# python-du
|
|
2
|
-
|
|
3
|
-
A disk usage analyzer that scans a directory and prints a visual tree map of folder sizes — right in your terminal.
|
|
4
|
-
|
|
5
|
-
## Example
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
$ python-du /usr -d 2 -m 2
|
|
9
|
-
usr [60.2 GB]
|
|
10
|
-
|
|
11
|
-
├── share 27.4 GB ( 45.6%) ▕█████████░░░░░░░░░░░▏
|
|
12
|
-
│ └── ollama 22.6 GB ( 37.5%) ▕███████░░░░░░░░░░░░░▏
|
|
13
|
-
│ └── .ollama 22.6 GB ( 37.5%) ▕███████░░░░░░░░░░░░░▏
|
|
14
|
-
├── lib 26.4 GB ( 43.8%) ▕████████░░░░░░░░░░░░▏
|
|
15
|
-
│ ├── x86_64-linux-gnu 11.7 GB ( 19.3%) ▕███░░░░░░░░░░░░░░░░░▏
|
|
16
|
-
│ ├── arm-none-eabi 2.7 GB ( 4.5%) ▕░░░░░░░░░░░░░░░░░░░░▏
|
|
17
|
-
│ ├── jvm 2.1 GB ( 3.5%) ▕░░░░░░░░░░░░░░░░░░░░▏
|
|
18
|
-
│ ├── dotnet 1.5 GB ( 2.5%) ▕░░░░░░░░░░░░░░░░░░░░▏
|
|
19
|
-
│ └── apache-netbeans 1.3 GB ( 2.2%) ▕░░░░░░░░░░░░░░░░░░░░▏
|
|
20
|
-
├── local 3.8 GB ( 6.3%) ▕█░░░░░░░░░░░░░░░░░░░▏
|
|
21
|
-
│ └── lib 3.2 GB ( 5.3%) ▕█░░░░░░░░░░░░░░░░░░░▏
|
|
22
|
-
├── bin 1.4 GB ( 2.4%) ▕░░░░░░░░░░░░░░░░░░░░▏
|
|
23
|
-
│ └── <files> 1.4 GB ( 2.4%) ▕░░░░░░░░░░░░░░░░░░░░▏
|
|
24
|
-
└── <files> 33.7 KB ( 0.0%) ▕░░░░░░░░░░░░░░░░░░░░▏
|
|
25
|
-
|
|
26
|
-
Total: 60.2 GB | 46966 directories, 390046 files
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
pip install -e .
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Usage
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
python-du [path] [options]
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
If no path is given, the current directory is scanned.
|
|
42
|
-
|
|
43
|
-
### Options
|
|
44
|
-
|
|
45
|
-
| Flag | Description |
|
|
46
|
-
|------|-------------|
|
|
47
|
-
| `-d`, `--max-depth N` | Maximum tree depth to display (default: 4) |
|
|
48
|
-
| `-m`, `--min-percent N` | Hide entries smaller than N% of total (default: 0.5) |
|
|
49
|
-
| `--no-color` | Disable colored output |
|
|
50
|
-
| `--sort-alpha` | Sort alphabetically instead of by size |
|
|
51
|
-
| `--scan-depth N` | Limit how deep the filesystem scan goes (default: unlimited) |
|
|
52
|
-
| `-L`, `--follow-symlinks` | Follow symbolic links |
|
|
53
|
-
|
|
54
|
-
### Examples
|
|
55
|
-
|
|
56
|
-
Scan the current directory with defaults:
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
python-du
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Scan `/var/log` showing only entries above 5%, two levels deep:
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
python-du /var/log -d 2 -m 5
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Pipe to a file (automatically disables color):
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
python-du /home > usage-report.txt
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Publishing to PyPI
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
pip install build twine
|
|
78
|
-
python -m build
|
|
79
|
-
twine upload dist/*
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
When prompted, use `__token__` as the username and your PyPI API token as the password.
|
|
83
|
-
|
|
84
|
-
To skip the prompt, create a `~/.pypirc` file:
|
|
85
|
-
|
|
86
|
-
```ini
|
|
87
|
-
[pypi]
|
|
88
|
-
username = __token__
|
|
89
|
-
password = pypi-YOUR-TOKEN-HERE
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
> **Note:** Bump the `version` in `pyproject.toml` before each upload — PyPI rejects duplicate version numbers.
|
|
93
|
-
|
|
94
|
-
## Requirements
|
|
95
|
-
|
|
96
|
-
- Python >= 3.9
|
|
97
|
-
- No external dependencies
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|