chtoolbox 1.2.0__tar.gz → 1.4.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.
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: chtoolbox
3
+ Version: 1.4.0
4
+ Summary: Various Python tools used in daily work
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/chagenvik/chtoolbox
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: numpy>=1.26.2
11
+ Requires-Dist: pandas>=2.1.4
12
+ Requires-Dist: pathspec>=0.12.1
13
+ Dynamic: license-file
14
+
15
+ # chtoolbox
16
+ chtoolbox is a library containing various python tools used in my daily work
17
+
18
+ ## Installation
19
+ To install chtoolbox, use pip:
20
+
21
+ ```sh
22
+ pip install chtoolbox
23
+ ```
24
+
25
+ ## Usage
26
+ Examples are provided in the `examples` folder in the repository.
27
+
28
+ ### Folder size check
29
+ Use `check_folder_sizes` to inspect the direct files and subfolders inside a folder. Subfolder sizes include all files recursively below each subfolder.
30
+
31
+ ```python
32
+ from chtoolbox.misc import check_folder_sizes
33
+
34
+ sizes = check_folder_sizes('.')
35
+ ```
36
+
37
+ After installing the package, you can also run the same check directly from CMD:
38
+
39
+ ```sh
40
+ chfolder-size
41
+ chfolder-size C:\path\to\folder
42
+ chfolder-size C:\path\to\folder --sort-by name --ascending
43
+ ```
44
+
45
+ If Windows blocks generated `.exe` launchers in your environment, run the same command through Python instead:
46
+
47
+ ```sh
48
+ python -m chtoolbox.folder_size
49
+ python -m chtoolbox.folder_size C:\path\to\folder
50
+ python -m chtoolbox.folder_size C:\path\to\folder --sort-by name --ascending
51
+ ```
52
+
53
+ ## License
54
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,40 @@
1
+ # chtoolbox
2
+ chtoolbox is a library containing various python tools used in my daily work
3
+
4
+ ## Installation
5
+ To install chtoolbox, use pip:
6
+
7
+ ```sh
8
+ pip install chtoolbox
9
+ ```
10
+
11
+ ## Usage
12
+ Examples are provided in the `examples` folder in the repository.
13
+
14
+ ### Folder size check
15
+ Use `check_folder_sizes` to inspect the direct files and subfolders inside a folder. Subfolder sizes include all files recursively below each subfolder.
16
+
17
+ ```python
18
+ from chtoolbox.misc import check_folder_sizes
19
+
20
+ sizes = check_folder_sizes('.')
21
+ ```
22
+
23
+ After installing the package, you can also run the same check directly from CMD:
24
+
25
+ ```sh
26
+ chfolder-size
27
+ chfolder-size C:\path\to\folder
28
+ chfolder-size C:\path\to\folder --sort-by name --ascending
29
+ ```
30
+
31
+ If Windows blocks generated `.exe` launchers in your environment, run the same command through Python instead:
32
+
33
+ ```sh
34
+ python -m chtoolbox.folder_size
35
+ python -m chtoolbox.folder_size C:\path\to\folder
36
+ python -m chtoolbox.folder_size C:\path\to\folder --sort-by name --ascending
37
+ ```
38
+
39
+ ## License
40
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,12 @@
1
+ """Command line entry point for folder size checks."""
2
+
3
+ from .misc import folder_sizes_cli
4
+
5
+
6
+ def main(argv=None):
7
+ """Run the folder size command line interface."""
8
+ folder_sizes_cli(argv)
9
+
10
+
11
+ if __name__ == '__main__':
12
+ main()
@@ -21,8 +21,113 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
22
  """
23
23
 
24
- import pandas as pd
25
24
  from itertools import product
25
+ from pathlib import Path
26
+ import argparse
27
+
28
+ import pandas as pd
29
+
30
+
31
+ def _get_path_size(path: Path) -> int:
32
+ """Return file bytes for a file or total recursive bytes for a folder."""
33
+ if path.is_file():
34
+ return path.stat().st_size
35
+
36
+ total_size = 0
37
+ for child in path.rglob('*'):
38
+ if child.is_file():
39
+ total_size += child.stat().st_size
40
+
41
+ return total_size
42
+
43
+
44
+ def _format_file_size(size_bytes: int) -> str:
45
+ """Format bytes as a compact human-readable file size."""
46
+ size = float(size_bytes)
47
+ for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
48
+ if size < 1024 or unit == 'TB':
49
+ if unit == 'B':
50
+ return f'{int(size)} {unit}'
51
+ return f'{size:.2f} {unit}'
52
+ size /= 1024
53
+
54
+
55
+ def check_folder_sizes(folder='.', sort_by='size', reverse=True):
56
+ """
57
+ Get sizes for direct files and subfolders inside a folder.
58
+
59
+ Subfolder sizes include all files recursively below each subfolder.
60
+
61
+ Parameters
62
+ ----------
63
+ folder : str or pathlib.Path, optional
64
+ Folder to inspect. Defaults to the current working folder.
65
+ sort_by : {'size', 'name', 'type'}, optional
66
+ Field used to sort the result. Defaults to 'size'.
67
+ reverse : bool, optional
68
+ Sort descending when True. Defaults to True.
69
+
70
+ Returns
71
+ -------
72
+ list of dict
73
+ One dictionary per direct child with name, path, type, size_bytes and size.
74
+
75
+ Examples
76
+ --------
77
+ >>> check_folder_sizes('.')
78
+ [{'name': 'README.md', 'path': 'README.md', 'type': 'file', 'size_bytes': 154, 'size': '154 B'}]
79
+ """
80
+ folder_path = Path(folder).expanduser().resolve()
81
+
82
+ if not folder_path.exists():
83
+ raise FileNotFoundError(f'Folder does not exist: {folder_path}')
84
+ if not folder_path.is_dir():
85
+ raise NotADirectoryError(f'Path is not a folder: {folder_path}')
86
+ if sort_by not in {'size', 'name', 'type'}:
87
+ raise ValueError("sort_by must be one of: 'size', 'name', 'type'")
88
+
89
+ items = []
90
+ for child in folder_path.iterdir():
91
+ size_bytes = _get_path_size(child)
92
+ items.append({
93
+ 'name': child.name,
94
+ 'path': str(child),
95
+ 'type': 'folder' if child.is_dir() else 'file',
96
+ 'size_bytes': size_bytes,
97
+ 'size': _format_file_size(size_bytes),
98
+ })
99
+
100
+ sort_key = 'size_bytes' if sort_by == 'size' else sort_by
101
+ return sorted(items, key=lambda item: item[sort_key], reverse=reverse)
102
+
103
+
104
+ def _print_folder_sizes(items):
105
+ """Print folder size results as a simple table."""
106
+ if not items:
107
+ print('No files or folders found.')
108
+ return
109
+
110
+ name_width = max(len('Name'), *(len(item['name']) for item in items))
111
+ type_width = max(len('Type'), *(len(item['type']) for item in items))
112
+ size_width = max(len('Size'), *(len(item['size']) for item in items))
113
+
114
+ print(f"{'Name':<{name_width}} {'Type':<{type_width}} {'Size':>{size_width}}")
115
+ print(f"{'-' * name_width} {'-' * type_width} {'-' * size_width}")
116
+ for item in items:
117
+ print(f"{item['name']:<{name_width}} {item['type']:<{type_width}} {item['size']:>{size_width}}")
118
+
119
+
120
+ def folder_sizes_cli(argv=None):
121
+ """Command line entry point for checking file and subfolder sizes."""
122
+ parser = argparse.ArgumentParser(description='Show sizes of files and subfolders in a folder.')
123
+ parser.add_argument('folder', nargs='?', default='.', help='Folder to inspect. Defaults to the current folder.')
124
+ parser.add_argument('--sort-by', choices=['size', 'name', 'type'], default='size', help='Sort output by this field.')
125
+ parser.add_argument('--ascending', action='store_true', help='Sort from smallest to largest or A to Z.')
126
+ args = parser.parse_args(argv)
127
+
128
+ items = check_folder_sizes(args.folder, sort_by=args.sort_by, reverse=not args.ascending)
129
+ _print_folder_sizes(items)
130
+
26
131
 
27
132
  def clipboard_to_dict(print_dict=True):
28
133
  """
@@ -247,4 +352,5 @@ def filter_dictionary(input_dict: dict, filter: str | list[str]) -> dict:
247
352
 
248
353
  filtered_dict = {key: value for key, value in input_dict.items() if any(f.lower() in key.lower() for f in filter)}
249
354
 
250
- return filtered_dict
355
+ return filtered_dict
356
+
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: chtoolbox
3
+ Version: 1.4.0
4
+ Summary: Various Python tools used in daily work
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/chagenvik/chtoolbox
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: numpy>=1.26.2
11
+ Requires-Dist: pandas>=2.1.4
12
+ Requires-Dist: pathspec>=0.12.1
13
+ Dynamic: license-file
14
+
15
+ # chtoolbox
16
+ chtoolbox is a library containing various python tools used in my daily work
17
+
18
+ ## Installation
19
+ To install chtoolbox, use pip:
20
+
21
+ ```sh
22
+ pip install chtoolbox
23
+ ```
24
+
25
+ ## Usage
26
+ Examples are provided in the `examples` folder in the repository.
27
+
28
+ ### Folder size check
29
+ Use `check_folder_sizes` to inspect the direct files and subfolders inside a folder. Subfolder sizes include all files recursively below each subfolder.
30
+
31
+ ```python
32
+ from chtoolbox.misc import check_folder_sizes
33
+
34
+ sizes = check_folder_sizes('.')
35
+ ```
36
+
37
+ After installing the package, you can also run the same check directly from CMD:
38
+
39
+ ```sh
40
+ chfolder-size
41
+ chfolder-size C:\path\to\folder
42
+ chfolder-size C:\path\to\folder --sort-by name --ascending
43
+ ```
44
+
45
+ If Windows blocks generated `.exe` launchers in your environment, run the same command through Python instead:
46
+
47
+ ```sh
48
+ python -m chtoolbox.folder_size
49
+ python -m chtoolbox.folder_size C:\path\to\folder
50
+ python -m chtoolbox.folder_size C:\path\to\folder --sort-by name --ascending
51
+ ```
52
+
53
+ ## License
54
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -1,14 +1,17 @@
1
1
  LICENSE
2
2
  README.md
3
- setup.py
3
+ pyproject.toml
4
+ requirements.txt
4
5
  chtoolbox/__init__.py
5
6
  chtoolbox/add_license.py
7
+ chtoolbox/folder_size.py
6
8
  chtoolbox/misc.py
7
9
  chtoolbox/testing.py
8
10
  chtoolbox.egg-info/PKG-INFO
9
11
  chtoolbox.egg-info/SOURCES.txt
10
12
  chtoolbox.egg-info/dependency_links.txt
13
+ chtoolbox.egg-info/entry_points.txt
11
14
  chtoolbox.egg-info/requires.txt
12
15
  chtoolbox.egg-info/top_level.txt
13
- tests/__init__.py
16
+ tests/test_misc.py
14
17
  tests/test_testing.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ chfolder-size = chtoolbox.folder_size:main
@@ -0,0 +1,23 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "chtoolbox"
7
+ version = "1.4.0"
8
+ description = "Various Python tools used in daily work"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dynamic = ["dependencies"]
12
+ license = "MIT"
13
+ license-files = ["LICENSE"]
14
+ urls = {Homepage = "https://github.com/chagenvik/chtoolbox"}
15
+
16
+ [project.scripts]
17
+ chfolder-size = "chtoolbox.folder_size:main"
18
+
19
+ [tool.setuptools.packages.find]
20
+ include = ["chtoolbox*"]
21
+
22
+ [tool.setuptools.dynamic]
23
+ dependencies = {file = ["requirements.txt"]}
@@ -0,0 +1,3 @@
1
+ numpy>=1.26.2
2
+ pandas>=2.1.4
3
+ pathspec>=0.12.1
@@ -0,0 +1,60 @@
1
+ """MIT License
2
+
3
+ Copyright (c) 2025 Christian Hågenvik
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+ """
23
+
24
+ from chtoolbox.misc import check_folder_sizes, folder_sizes_cli
25
+
26
+
27
+ def test_check_folder_sizes_includes_files_and_recursive_folder_size(tmp_path):
28
+ file_path = tmp_path / 'file.txt'
29
+ file_path.write_text('abcd')
30
+
31
+ subfolder = tmp_path / 'subfolder'
32
+ subfolder.mkdir()
33
+ (subfolder / 'nested.txt').write_text('123456')
34
+
35
+ result = check_folder_sizes(tmp_path)
36
+ result_by_name = {item['name']: item for item in result}
37
+
38
+ assert result_by_name['file.txt']['type'] == 'file'
39
+ assert result_by_name['file.txt']['size_bytes'] == 4
40
+ assert result_by_name['subfolder']['type'] == 'folder'
41
+ assert result_by_name['subfolder']['size_bytes'] == 6
42
+
43
+
44
+ def test_check_folder_sizes_can_sort_by_name(tmp_path):
45
+ (tmp_path / 'b.txt').write_text('b')
46
+ (tmp_path / 'a.txt').write_text('a')
47
+
48
+ result = check_folder_sizes(tmp_path, sort_by='name', reverse=False)
49
+
50
+ assert [item['name'] for item in result] == ['a.txt', 'b.txt']
51
+
52
+
53
+ def test_folder_sizes_cli_prints_requested_folder(tmp_path, capsys):
54
+ (tmp_path / 'file.txt').write_text('abcd')
55
+
56
+ folder_sizes_cli([str(tmp_path), '--sort-by', 'name', '--ascending'])
57
+
58
+ output = capsys.readouterr().out
59
+ assert 'file.txt' in output
60
+ assert '4 B' in output
chtoolbox-1.2.0/PKG-INFO DELETED
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: chtoolbox
3
- Version: 1.2.0
4
- Home-page: https://github.com/chagenvik/chtoolbox
5
- Description-Content-Type: text/markdown
6
- License-File: LICENSE
7
-
8
- # chtoolbox
9
- chtoolbox is a library containing various python tools used in my daily work
10
-
11
- ## Installation
12
- To install chtoolbox, use pip:
13
-
14
- ```sh
15
- pip install chtoolbox
16
- ```
17
-
18
- ## Usage
19
- Examples are provided in the `examples` folder in the repository.
20
-
21
- ## License
22
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
chtoolbox-1.2.0/README.md DELETED
@@ -1,15 +0,0 @@
1
- # chtoolbox
2
- chtoolbox is a library containing various python tools used in my daily work
3
-
4
- ## Installation
5
- To install chtoolbox, use pip:
6
-
7
- ```sh
8
- pip install chtoolbox
9
- ```
10
-
11
- ## Usage
12
- Examples are provided in the `examples` folder in the repository.
13
-
14
- ## License
15
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: chtoolbox
3
- Version: 1.2.0
4
- Home-page: https://github.com/chagenvik/chtoolbox
5
- Description-Content-Type: text/markdown
6
- License-File: LICENSE
7
-
8
- # chtoolbox
9
- chtoolbox is a library containing various python tools used in my daily work
10
-
11
- ## Installation
12
- To install chtoolbox, use pip:
13
-
14
- ```sh
15
- pip install chtoolbox
16
- ```
17
-
18
- ## Usage
19
- Examples are provided in the `examples` folder in the repository.
20
-
21
- ## License
22
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
chtoolbox-1.2.0/setup.py DELETED
@@ -1,46 +0,0 @@
1
- """MIT License
2
-
3
- Copyright (c) 2025 Christian Hågenvik
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
22
- """
23
-
24
- from setuptools import setup, find_packages
25
- from pathlib import Path
26
-
27
- # Read the requirements from the requirements.txt file
28
- requirements_path = Path(__file__).parent / 'requirements.txt'
29
- with requirements_path.open() as requirements_file:
30
- requirements = requirements_file.read().splitlines()
31
-
32
- # Read the contents of the README file
33
- readme_path = Path(__file__).parent / 'README.md'
34
- with readme_path.open() as readme_file:
35
- long_description = readme_file.read()
36
-
37
- setup(
38
- name='chtoolbox',
39
- version='1.2.0',
40
- packages=find_packages(),
41
- install_requires=requirements,
42
- long_description=long_description,
43
- long_description_content_type='text/markdown',
44
- url='https://github.com/chagenvik/chtoolbox'
45
- )
46
-
@@ -1,23 +0,0 @@
1
- """MIT License
2
-
3
- Copyright (c) 2025 Christian Hågenvik
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
22
- """
23
-
File without changes
File without changes