killpy 0.21.0__tar.gz → 0.22.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {killpy-0.21.0 → killpy-0.22.0}/PKG-INFO +37 -7
- {killpy-0.21.0 → killpy-0.22.0}/README.md +36 -6
- {killpy-0.21.0 → killpy-0.22.0}/killpy/__main__.py +2 -0
- killpy-0.22.0/killpy/commands/_utils.py +65 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/commands/clean.py +2 -4
- {killpy-0.21.0 → killpy-0.22.0}/killpy/commands/delete.py +2 -22
- {killpy-0.21.0 → killpy-0.22.0}/killpy/commands/doctor.py +3 -9
- {killpy-0.21.0 → killpy-0.22.0}/killpy/commands/list.py +3 -25
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/artifacts.py +2 -2
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/conda.py +0 -1
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/hatch.py +2 -2
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/pipenv.py +2 -2
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/poetry.py +2 -2
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/pyenv.py +2 -2
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/tox.py +2 -2
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/uv.py +2 -2
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/venv.py +0 -1
- {killpy-0.21.0 → killpy-0.22.0}/killpy.egg-info/PKG-INFO +37 -7
- {killpy-0.21.0 → killpy-0.22.0}/killpy.egg-info/SOURCES.txt +1 -0
- {killpy-0.21.0 → killpy-0.22.0}/pyproject.toml +1 -1
- {killpy-0.21.0 → killpy-0.22.0}/killpy/__init__.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/cleaner.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/cleaners/__init__.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/cli.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/commands/__init__.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/commands/stats.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/__init__.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/base.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/cache.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/detectors/pipx.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/files/__init__.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/intelligence/__init__.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/intelligence/git_analyzer.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/intelligence/scoring.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/intelligence/suggestions.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/intelligence/tracker.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/models.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy/scanner.py +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy.egg-info/dependency_links.txt +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy.egg-info/entry_points.txt +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy.egg-info/requires.txt +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/killpy.egg-info/top_level.txt +0 -0
- {killpy-0.21.0 → killpy-0.22.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: killpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.0
|
|
4
4
|
Summary: List all .venv directories and Conda environments 🐍 on your system and check how much space they are using. You can then choose which ones to delete in order to free up space 🧹.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Tlaloc-Es/killpy
|
|
6
6
|
Project-URL: Documentation, https://tlaloc-es.github.io/killpy/
|
|
@@ -22,9 +22,13 @@ Requires-Dist: textual>=1.0.0
|
|
|
22
22
|
|
|
23
23
|

|
|
24
24
|
|
|
25
|
-
###
|
|
25
|
+
### Free GBs of disk space by removing unused Python environments
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Find and delete old `.venv`, conda, poetry, pipenv, uv and more — safely, in seconds.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uvx killpy --path ~
|
|
31
|
+
```
|
|
28
32
|
|
|
29
33
|
[Documentation](https://tlaloc-es.github.io/killpy/)
|
|
30
34
|
|
|
@@ -515,18 +519,44 @@ Each virtual environment is a full copy (or symlinked tree) of a Python interpre
|
|
|
515
519
|
|
|
516
520
|
______________________________________________________________________
|
|
517
521
|
|
|
518
|
-
## Pre-commit
|
|
522
|
+
## Pre-commit hooks
|
|
523
|
+
|
|
524
|
+
`killpy` ships four hooks for [pre-commit](https://pre-commit.com/). Add the ones you need to your `.pre-commit-config.yaml`:
|
|
525
|
+
|
|
526
|
+
```yaml
|
|
527
|
+
- repo: https://github.com/Tlaloc-Es/KillPy
|
|
528
|
+
rev: 0.20.0
|
|
529
|
+
hooks:
|
|
530
|
+
- id: killpy # remove __pycache__ on every commit
|
|
531
|
+
- id: killpy-clean-caches # also removes .mypy_cache, .pytest_cache, .ruff_cache
|
|
532
|
+
- id: killpy-clean-artifacts # remove dist/, build/, *.egg-info before committing
|
|
533
|
+
- id: killpy-remove-venv # remove .venv (manual stage — see below)
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
| Hook id | What it removes | Default stage |
|
|
537
|
+
|---------|-----------------|---------------|
|
|
538
|
+
| `killpy` | `__pycache__` directories | `pre-commit` |
|
|
539
|
+
| `killpy-clean-caches` | All local cache dirs (`__pycache__`, `.mypy_cache`, `.pytest_cache`, `.ruff_cache`) | `pre-commit` |
|
|
540
|
+
| `killpy-clean-artifacts` | Build artifacts (`dist/`, `build/`, `*.egg-info`) | `pre-commit` |
|
|
541
|
+
| `killpy-remove-venv` | Local `.venv` environments | `manual` |
|
|
542
|
+
|
|
543
|
+
**`killpy-remove-venv`** is staged as `manual` because deleting the environment on every commit would require you to recreate it each time. Run it explicitly when you want a clean slate:
|
|
519
544
|
|
|
520
|
-
|
|
545
|
+
```bash
|
|
546
|
+
pre-commit run killpy-remove-venv --hook-stage manual
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
Typical minimal setup (safe for daily use):
|
|
521
550
|
|
|
522
551
|
```yaml
|
|
523
552
|
- repo: https://github.com/Tlaloc-Es/KillPy
|
|
524
|
-
rev: 0.
|
|
553
|
+
rev: 0.22.0
|
|
525
554
|
hooks:
|
|
526
555
|
- id: killpy
|
|
527
|
-
pass_filenames: false
|
|
528
556
|
```
|
|
529
557
|
|
|
558
|
+
Add `killpy-clean-artifacts` if your project generates `dist/` or `build/` locally and you want to guarantee they are never staged by accident.
|
|
559
|
+
|
|
530
560
|
______________________________________________________________________
|
|
531
561
|
|
|
532
562
|
## Safety
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
###
|
|
5
|
+
### Free GBs of disk space by removing unused Python environments
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Find and delete old `.venv`, conda, poetry, pipenv, uv and more — safely, in seconds.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uvx killpy --path ~
|
|
11
|
+
```
|
|
8
12
|
|
|
9
13
|
[Documentation](https://tlaloc-es.github.io/killpy/)
|
|
10
14
|
|
|
@@ -495,18 +499,44 @@ Each virtual environment is a full copy (or symlinked tree) of a Python interpre
|
|
|
495
499
|
|
|
496
500
|
______________________________________________________________________
|
|
497
501
|
|
|
498
|
-
## Pre-commit
|
|
502
|
+
## Pre-commit hooks
|
|
503
|
+
|
|
504
|
+
`killpy` ships four hooks for [pre-commit](https://pre-commit.com/). Add the ones you need to your `.pre-commit-config.yaml`:
|
|
505
|
+
|
|
506
|
+
```yaml
|
|
507
|
+
- repo: https://github.com/Tlaloc-Es/KillPy
|
|
508
|
+
rev: 0.20.0
|
|
509
|
+
hooks:
|
|
510
|
+
- id: killpy # remove __pycache__ on every commit
|
|
511
|
+
- id: killpy-clean-caches # also removes .mypy_cache, .pytest_cache, .ruff_cache
|
|
512
|
+
- id: killpy-clean-artifacts # remove dist/, build/, *.egg-info before committing
|
|
513
|
+
- id: killpy-remove-venv # remove .venv (manual stage — see below)
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
| Hook id | What it removes | Default stage |
|
|
517
|
+
|---------|-----------------|---------------|
|
|
518
|
+
| `killpy` | `__pycache__` directories | `pre-commit` |
|
|
519
|
+
| `killpy-clean-caches` | All local cache dirs (`__pycache__`, `.mypy_cache`, `.pytest_cache`, `.ruff_cache`) | `pre-commit` |
|
|
520
|
+
| `killpy-clean-artifacts` | Build artifacts (`dist/`, `build/`, `*.egg-info`) | `pre-commit` |
|
|
521
|
+
| `killpy-remove-venv` | Local `.venv` environments | `manual` |
|
|
522
|
+
|
|
523
|
+
**`killpy-remove-venv`** is staged as `manual` because deleting the environment on every commit would require you to recreate it each time. Run it explicitly when you want a clean slate:
|
|
499
524
|
|
|
500
|
-
|
|
525
|
+
```bash
|
|
526
|
+
pre-commit run killpy-remove-venv --hook-stage manual
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Typical minimal setup (safe for daily use):
|
|
501
530
|
|
|
502
531
|
```yaml
|
|
503
532
|
- repo: https://github.com/Tlaloc-Es/KillPy
|
|
504
|
-
rev: 0.
|
|
533
|
+
rev: 0.22.0
|
|
505
534
|
hooks:
|
|
506
535
|
- id: killpy
|
|
507
|
-
pass_filenames: false
|
|
508
536
|
```
|
|
509
537
|
|
|
538
|
+
Add `killpy-clean-artifacts` if your project generates `dist/` or `build/` locally and you want to guarantee they are never staged by accident.
|
|
539
|
+
|
|
510
540
|
______________________________________________________________________
|
|
511
541
|
|
|
512
542
|
## Safety
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
|
|
3
4
|
import click
|
|
@@ -102,6 +103,7 @@ def _run_delete_all(path: Path, excluded: set[str], yes: bool) -> None:
|
|
|
102
103
|
)
|
|
103
104
|
@click.pass_context
|
|
104
105
|
def cli(ctx, path: Path, exclude: str, delete_all: bool, yes: bool):
|
|
106
|
+
logging.basicConfig(level=logging.WARNING)
|
|
105
107
|
excluded = (
|
|
106
108
|
{p.strip() for p in exclude.split(",") if p.strip()} if exclude else set()
|
|
107
109
|
)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Shared helpers for ``killpy`` commands."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime, timedelta, timezone
|
|
6
|
+
|
|
7
|
+
from killpy.models import Environment
|
|
8
|
+
|
|
9
|
+
# Maps user-facing type names (detector names) to the concrete ``Environment.type``
|
|
10
|
+
# values those detectors produce. Two detectors use sub-type tags instead of
|
|
11
|
+
# their own name: VenvDetector (tags: ".venv", "pyvenv.cfg") and CacheDetector
|
|
12
|
+
# (tags: "__pycache__", ".mypy_cache", ".pytest_cache", ".ruff_cache",
|
|
13
|
+
# "pip-cache", "uv-cache"). Without this mapping, ``--type venv`` and
|
|
14
|
+
# ``--type cache`` would never match anything.
|
|
15
|
+
_TYPE_ALIASES: dict[str, frozenset[str]] = {
|
|
16
|
+
"venv": frozenset({".venv", "pyvenv.cfg"}),
|
|
17
|
+
"cache": frozenset(
|
|
18
|
+
{
|
|
19
|
+
"__pycache__",
|
|
20
|
+
".mypy_cache",
|
|
21
|
+
".pytest_cache",
|
|
22
|
+
".ruff_cache",
|
|
23
|
+
"pip-cache",
|
|
24
|
+
"uv-cache",
|
|
25
|
+
}
|
|
26
|
+
),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def filter_envs(
|
|
31
|
+
envs: list[Environment],
|
|
32
|
+
types: tuple[str, ...] | None,
|
|
33
|
+
older_than: int | None,
|
|
34
|
+
) -> list[Environment]:
|
|
35
|
+
"""Return a filtered subset of *envs*.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
envs:
|
|
40
|
+
Full list of detected environments.
|
|
41
|
+
types:
|
|
42
|
+
If provided, only environments whose :attr:`~killpy.models.Environment.type`
|
|
43
|
+
matches one of these strings (case-insensitive) are kept. Detector
|
|
44
|
+
names such as ``"venv"`` and ``"cache"`` are automatically expanded to
|
|
45
|
+
their concrete sub-type values via :data:`_TYPE_ALIASES`.
|
|
46
|
+
older_than:
|
|
47
|
+
If provided, only environments not accessed in the last *older_than* days
|
|
48
|
+
are kept.
|
|
49
|
+
"""
|
|
50
|
+
now = datetime.now(tz=timezone.utc)
|
|
51
|
+
result = envs
|
|
52
|
+
|
|
53
|
+
if types:
|
|
54
|
+
expanded: set[str] = set()
|
|
55
|
+
for t in types:
|
|
56
|
+
t_lower = t.strip().lower()
|
|
57
|
+
expanded.add(t_lower)
|
|
58
|
+
expanded.update(_TYPE_ALIASES.get(t_lower, frozenset()))
|
|
59
|
+
result = [e for e in result if e.type.lower() in expanded]
|
|
60
|
+
|
|
61
|
+
if older_than is not None:
|
|
62
|
+
cutoff = now - timedelta(days=older_than)
|
|
63
|
+
result = [e for e in result if e.last_accessed < cutoff]
|
|
64
|
+
|
|
65
|
+
return result
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
from pathlib import Path
|
|
3
2
|
|
|
4
3
|
import click
|
|
@@ -10,8 +9,7 @@ from killpy.files import format_size
|
|
|
10
9
|
@click.command()
|
|
11
10
|
@click.option("--path", default=Path.cwd(), help="Path to the directory to clean")
|
|
12
11
|
def clean(path):
|
|
13
|
-
logging.basicConfig(level=logging.INFO)
|
|
14
12
|
path = Path(path)
|
|
15
|
-
|
|
13
|
+
click.echo(f"Cleaning {path}…")
|
|
16
14
|
total_freed_space = remove_pycache(path)
|
|
17
|
-
|
|
15
|
+
click.echo(f"{format_size(total_freed_space)} freed")
|
|
@@ -3,38 +3,18 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import sys
|
|
6
|
-
from datetime import datetime, timedelta, timezone
|
|
7
6
|
from pathlib import Path
|
|
8
7
|
|
|
9
8
|
import click
|
|
10
9
|
from rich.console import Console
|
|
11
10
|
|
|
12
11
|
from killpy.cleaner import Cleaner, CleanerError
|
|
12
|
+
from killpy.commands._utils import filter_envs
|
|
13
13
|
from killpy.files import format_size
|
|
14
14
|
from killpy.intelligence.tracker import UsageTracker
|
|
15
|
-
from killpy.models import Environment
|
|
16
15
|
from killpy.scanner import Scanner
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
def _filter_envs(
|
|
20
|
-
envs: list[Environment],
|
|
21
|
-
types: tuple[str, ...] | None,
|
|
22
|
-
older_than: int | None,
|
|
23
|
-
) -> list[Environment]:
|
|
24
|
-
now = datetime.now(tz=timezone.utc)
|
|
25
|
-
result = envs
|
|
26
|
-
|
|
27
|
-
if types:
|
|
28
|
-
type_set = {t.strip().lower() for t in types}
|
|
29
|
-
result = [e for e in result if e.type.lower() in type_set]
|
|
30
|
-
|
|
31
|
-
if older_than is not None:
|
|
32
|
-
cutoff = now - timedelta(days=older_than)
|
|
33
|
-
result = [e for e in result if e.last_accessed < cutoff]
|
|
34
|
-
|
|
35
|
-
return result
|
|
36
|
-
|
|
37
|
-
|
|
38
18
|
@click.command("delete")
|
|
39
19
|
@click.option(
|
|
40
20
|
"--path",
|
|
@@ -88,7 +68,7 @@ def delete_cmd(
|
|
|
88
68
|
|
|
89
69
|
scanner = Scanner(types=set(types) if types else None)
|
|
90
70
|
envs = scanner.scan(path)
|
|
91
|
-
envs =
|
|
71
|
+
envs = filter_envs(envs, types or None, older_than)
|
|
92
72
|
|
|
93
73
|
if not envs:
|
|
94
74
|
console.print("[yellow]No environments found matching the criteria.[/yellow]")
|
|
@@ -10,6 +10,7 @@ import click
|
|
|
10
10
|
from rich.console import Console
|
|
11
11
|
from rich.table import Table
|
|
12
12
|
|
|
13
|
+
from killpy.detectors import ALL_DETECTORS
|
|
13
14
|
from killpy.files import format_size
|
|
14
15
|
from killpy.intelligence import SuggestionEngine, UsageTracker, score_all
|
|
15
16
|
from killpy.models import Suggestion
|
|
@@ -29,16 +30,9 @@ _TOP_N = 5
|
|
|
29
30
|
|
|
30
31
|
# Detectors that surface virtual environments. Cache / artifact detectors
|
|
31
32
|
# are intentionally excluded from doctor – use `killpy clean` for those.
|
|
33
|
+
_CACHE_ARTIFACT_TYPES: frozenset[str] = frozenset({"cache", "artifacts"})
|
|
32
34
|
_ENV_TYPES: set[str] = {
|
|
33
|
-
|
|
34
|
-
"poetry",
|
|
35
|
-
"conda",
|
|
36
|
-
"pipx",
|
|
37
|
-
"pyenv",
|
|
38
|
-
"pipenv",
|
|
39
|
-
"hatch",
|
|
40
|
-
"uv",
|
|
41
|
-
"tox",
|
|
35
|
+
cls.name for cls in ALL_DETECTORS if cls.name not in _CACHE_ARTIFACT_TYPES
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
|
|
@@ -3,39 +3,17 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
|
-
from datetime import datetime, timedelta, timezone
|
|
7
6
|
from pathlib import Path
|
|
8
7
|
|
|
9
8
|
import click
|
|
10
9
|
from rich.console import Console
|
|
11
10
|
from rich.table import Table
|
|
12
11
|
|
|
12
|
+
from killpy.commands._utils import filter_envs
|
|
13
13
|
from killpy.files import format_size
|
|
14
|
-
from killpy.models import Environment
|
|
15
14
|
from killpy.scanner import Scanner
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
def _filter_envs(
|
|
19
|
-
envs: list[Environment],
|
|
20
|
-
types: tuple[str, ...] | None,
|
|
21
|
-
older_than: int | None,
|
|
22
|
-
) -> list[Environment]:
|
|
23
|
-
now = datetime.now(tz=timezone.utc)
|
|
24
|
-
result = envs
|
|
25
|
-
|
|
26
|
-
if types:
|
|
27
|
-
type_set = {t.strip().lower() for t in types}
|
|
28
|
-
result = [e for e in result if e.type.lower() in type_set]
|
|
29
|
-
|
|
30
|
-
if older_than is not None:
|
|
31
|
-
cutoff = now - timedelta(days=older_than)
|
|
32
|
-
result = [
|
|
33
|
-
e for e in result if e.last_accessed < cutoff
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
return result
|
|
37
|
-
|
|
38
|
-
|
|
39
17
|
@click.command("list")
|
|
40
18
|
@click.option(
|
|
41
19
|
"--path",
|
|
@@ -87,14 +65,14 @@ def list_cmd(
|
|
|
87
65
|
if as_json_stream:
|
|
88
66
|
|
|
89
67
|
def _stream_progress(_detector, envs):
|
|
90
|
-
for env in
|
|
68
|
+
for env in filter_envs(envs, types or None, older_than):
|
|
91
69
|
click.echo(json.dumps(env.to_dict()))
|
|
92
70
|
|
|
93
71
|
scanner.scan(path, on_progress=_stream_progress)
|
|
94
72
|
return
|
|
95
73
|
|
|
96
74
|
envs = scanner.scan(path)
|
|
97
|
-
envs =
|
|
75
|
+
envs = filter_envs(envs, types or None, older_than)
|
|
98
76
|
|
|
99
77
|
if as_json:
|
|
100
78
|
click.echo(json.dumps([e.to_dict() for e in envs], indent=2))
|
|
@@ -50,7 +50,8 @@ class ArtifactsDetector(AbstractDetector):
|
|
|
50
50
|
stat = artifact_path.stat()
|
|
51
51
|
size = get_total_size(artifact_path)
|
|
52
52
|
mtime = datetime.fromtimestamp(
|
|
53
|
-
stat.st_mtime,
|
|
53
|
+
stat.st_mtime,
|
|
54
|
+
tz=timezone.utc,
|
|
54
55
|
)
|
|
55
56
|
envs.append(
|
|
56
57
|
Environment(
|
|
@@ -66,5 +67,4 @@ class ArtifactsDetector(AbstractDetector):
|
|
|
66
67
|
pruned.add(d) # don't recurse inside
|
|
67
68
|
directories[:] = [d for d in directories if d not in pruned]
|
|
68
69
|
|
|
69
|
-
envs.sort(key=lambda e: e.size_bytes, reverse=True)
|
|
70
70
|
return envs
|
|
@@ -56,7 +56,8 @@ class HatchDetector(AbstractDetector):
|
|
|
56
56
|
stat = env_dir.stat()
|
|
57
57
|
size = get_total_size(env_dir)
|
|
58
58
|
mtime = datetime.fromtimestamp(
|
|
59
|
-
stat.st_mtime,
|
|
59
|
+
stat.st_mtime,
|
|
60
|
+
tz=timezone.utc,
|
|
60
61
|
)
|
|
61
62
|
envs.append(
|
|
62
63
|
Environment(
|
|
@@ -73,5 +74,4 @@ class HatchDetector(AbstractDetector):
|
|
|
73
74
|
logger.error("Cannot inspect hatch envs root: %s", exc)
|
|
74
75
|
return []
|
|
75
76
|
|
|
76
|
-
envs.sort(key=lambda e: e.size_bytes, reverse=True)
|
|
77
77
|
return envs
|
|
@@ -49,7 +49,8 @@ class PipenvDetector(AbstractDetector):
|
|
|
49
49
|
stat = venv_path.stat()
|
|
50
50
|
size = get_total_size(venv_path)
|
|
51
51
|
mtime = datetime.fromtimestamp(
|
|
52
|
-
stat.st_mtime,
|
|
52
|
+
stat.st_mtime,
|
|
53
|
+
tz=timezone.utc,
|
|
53
54
|
)
|
|
54
55
|
envs.append(
|
|
55
56
|
Environment(
|
|
@@ -66,5 +67,4 @@ class PipenvDetector(AbstractDetector):
|
|
|
66
67
|
logger.error("Cannot inspect pipenv venvs root: %s", exc)
|
|
67
68
|
return []
|
|
68
69
|
|
|
69
|
-
envs.sort(key=lambda e: e.size_bytes, reverse=True)
|
|
70
70
|
return envs
|
|
@@ -49,7 +49,8 @@ class PoetryDetector(AbstractDetector):
|
|
|
49
49
|
stat = venv_path.stat()
|
|
50
50
|
size = get_total_size(venv_path)
|
|
51
51
|
mtime = datetime.fromtimestamp(
|
|
52
|
-
stat.st_mtime,
|
|
52
|
+
stat.st_mtime,
|
|
53
|
+
tz=timezone.utc,
|
|
53
54
|
)
|
|
54
55
|
envs.append(
|
|
55
56
|
Environment(
|
|
@@ -69,5 +70,4 @@ class PoetryDetector(AbstractDetector):
|
|
|
69
70
|
logger.error("Cannot inspect poetry virtualenvs dir: %s", exc)
|
|
70
71
|
return []
|
|
71
72
|
|
|
72
|
-
envs.sort(key=lambda e: e.size_bytes, reverse=True)
|
|
73
73
|
return envs
|
|
@@ -50,7 +50,8 @@ class PyenvDetector(AbstractDetector):
|
|
|
50
50
|
stat = version_dir.stat()
|
|
51
51
|
size = get_total_size(version_dir)
|
|
52
52
|
mtime = datetime.fromtimestamp(
|
|
53
|
-
stat.st_mtime,
|
|
53
|
+
stat.st_mtime,
|
|
54
|
+
tz=timezone.utc,
|
|
54
55
|
)
|
|
55
56
|
envs.append(
|
|
56
57
|
Environment(
|
|
@@ -67,5 +68,4 @@ class PyenvDetector(AbstractDetector):
|
|
|
67
68
|
logger.error("Cannot inspect pyenv versions root: %s", exc)
|
|
68
69
|
return []
|
|
69
70
|
|
|
70
|
-
envs.sort(key=lambda e: e.size_bytes, reverse=True)
|
|
71
71
|
return envs
|
|
@@ -38,7 +38,8 @@ class ToxDetector(AbstractDetector):
|
|
|
38
38
|
stat = tox_path.stat()
|
|
39
39
|
size = get_total_size(tox_path)
|
|
40
40
|
mtime = datetime.fromtimestamp(
|
|
41
|
-
stat.st_mtime,
|
|
41
|
+
stat.st_mtime,
|
|
42
|
+
tz=timezone.utc,
|
|
42
43
|
)
|
|
43
44
|
envs.append(
|
|
44
45
|
Environment(
|
|
@@ -54,5 +55,4 @@ class ToxDetector(AbstractDetector):
|
|
|
54
55
|
pruned.add(d)
|
|
55
56
|
directories[:] = [d for d in directories if d not in pruned]
|
|
56
57
|
|
|
57
|
-
envs.sort(key=lambda e: e.size_bytes, reverse=True)
|
|
58
58
|
return envs
|
|
@@ -44,7 +44,8 @@ class UvDetector(AbstractDetector):
|
|
|
44
44
|
stat = uv_path.stat()
|
|
45
45
|
size = get_total_size(uv_path)
|
|
46
46
|
mtime = datetime.fromtimestamp(
|
|
47
|
-
stat.st_mtime,
|
|
47
|
+
stat.st_mtime,
|
|
48
|
+
tz=timezone.utc,
|
|
48
49
|
)
|
|
49
50
|
envs.append(
|
|
50
51
|
Environment(
|
|
@@ -60,5 +61,4 @@ class UvDetector(AbstractDetector):
|
|
|
60
61
|
pruned.add(d)
|
|
61
62
|
directories[:] = [d for d in directories if d not in pruned]
|
|
62
63
|
|
|
63
|
-
envs.sort(key=lambda e: e.size_bytes, reverse=True)
|
|
64
64
|
return envs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: killpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.0
|
|
4
4
|
Summary: List all .venv directories and Conda environments 🐍 on your system and check how much space they are using. You can then choose which ones to delete in order to free up space 🧹.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Tlaloc-Es/killpy
|
|
6
6
|
Project-URL: Documentation, https://tlaloc-es.github.io/killpy/
|
|
@@ -22,9 +22,13 @@ Requires-Dist: textual>=1.0.0
|
|
|
22
22
|
|
|
23
23
|

|
|
24
24
|
|
|
25
|
-
###
|
|
25
|
+
### Free GBs of disk space by removing unused Python environments
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Find and delete old `.venv`, conda, poetry, pipenv, uv and more — safely, in seconds.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uvx killpy --path ~
|
|
31
|
+
```
|
|
28
32
|
|
|
29
33
|
[Documentation](https://tlaloc-es.github.io/killpy/)
|
|
30
34
|
|
|
@@ -515,18 +519,44 @@ Each virtual environment is a full copy (or symlinked tree) of a Python interpre
|
|
|
515
519
|
|
|
516
520
|
______________________________________________________________________
|
|
517
521
|
|
|
518
|
-
## Pre-commit
|
|
522
|
+
## Pre-commit hooks
|
|
523
|
+
|
|
524
|
+
`killpy` ships four hooks for [pre-commit](https://pre-commit.com/). Add the ones you need to your `.pre-commit-config.yaml`:
|
|
525
|
+
|
|
526
|
+
```yaml
|
|
527
|
+
- repo: https://github.com/Tlaloc-Es/KillPy
|
|
528
|
+
rev: 0.20.0
|
|
529
|
+
hooks:
|
|
530
|
+
- id: killpy # remove __pycache__ on every commit
|
|
531
|
+
- id: killpy-clean-caches # also removes .mypy_cache, .pytest_cache, .ruff_cache
|
|
532
|
+
- id: killpy-clean-artifacts # remove dist/, build/, *.egg-info before committing
|
|
533
|
+
- id: killpy-remove-venv # remove .venv (manual stage — see below)
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
| Hook id | What it removes | Default stage |
|
|
537
|
+
|---------|-----------------|---------------|
|
|
538
|
+
| `killpy` | `__pycache__` directories | `pre-commit` |
|
|
539
|
+
| `killpy-clean-caches` | All local cache dirs (`__pycache__`, `.mypy_cache`, `.pytest_cache`, `.ruff_cache`) | `pre-commit` |
|
|
540
|
+
| `killpy-clean-artifacts` | Build artifacts (`dist/`, `build/`, `*.egg-info`) | `pre-commit` |
|
|
541
|
+
| `killpy-remove-venv` | Local `.venv` environments | `manual` |
|
|
542
|
+
|
|
543
|
+
**`killpy-remove-venv`** is staged as `manual` because deleting the environment on every commit would require you to recreate it each time. Run it explicitly when you want a clean slate:
|
|
519
544
|
|
|
520
|
-
|
|
545
|
+
```bash
|
|
546
|
+
pre-commit run killpy-remove-venv --hook-stage manual
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
Typical minimal setup (safe for daily use):
|
|
521
550
|
|
|
522
551
|
```yaml
|
|
523
552
|
- repo: https://github.com/Tlaloc-Es/KillPy
|
|
524
|
-
rev: 0.
|
|
553
|
+
rev: 0.22.0
|
|
525
554
|
hooks:
|
|
526
555
|
- id: killpy
|
|
527
|
-
pass_filenames: false
|
|
528
556
|
```
|
|
529
557
|
|
|
558
|
+
Add `killpy-clean-artifacts` if your project generates `dist/` or `build/` locally and you want to guarantee they are never staged by accident.
|
|
559
|
+
|
|
530
560
|
______________________________________________________________________
|
|
531
561
|
|
|
532
562
|
## Safety
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "killpy"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.22.0"
|
|
4
4
|
description = "List all .venv directories and Conda environments 🐍 on your system and check how much space they are using. You can then choose which ones to delete in order to free up space 🧹."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
classifiers = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|