splitzip 0.1.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,10 @@
1
+ venv/
2
+ .venv/
3
+ __pycache__/
4
+ *.pyc
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .mypy_cache/
9
+ .pytest_cache/
10
+ .ruff_cache/
splitzip-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jimothy
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.
@@ -0,0 +1,228 @@
1
+ Metadata-Version: 2.4
2
+ Name: splitzip
3
+ Version: 0.1.0
4
+ Summary: Create split ZIP archives compatible with standard tools
5
+ Project-URL: Homepage, https://github.com/twwat/splitzip
6
+ Project-URL: Repository, https://github.com/twwat/splitzip
7
+ Project-URL: Issues, https://github.com/twwat/splitzip/issues
8
+ Author-email: twwat <mailto.yourusername@wwwcomdot.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: 7z,archive,compression,multipart,split,zip
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: System :: Archiving :: Compression
24
+ Requires-Python: >=3.9
25
+ Provides-Extra: dev
26
+ Requires-Dist: mypy>=1.0; extra == 'dev'
27
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
28
+ Requires-Dist: pytest>=7.0; extra == 'dev'
29
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ [![PyPI version](https://badge.fury.io/py/splitzip.svg)](https://pypi.org/project/splitzip/) [![Python versions](https://img.shields.io/pypi/pyversions/splitzip)](https://pypi.org/project/splitzip/) [![License: MIT](https://img.shields.io/pypi/l/splitzip)](https://opensource.org/licenses/MIT)
33
+
34
+ # splitzip
35
+
36
+ Create split ZIP archives compatible with standard tools.
37
+
38
+ **No 7-Zip required.** Archives created with splitzip can be extracted using Windows Explorer, WinZip, macOS Archive Utility, and standard `unzip` on Linux.
39
+
40
+ ## Features
41
+
42
+ - Pure Python, no external dependencies
43
+ - Compatible with standard ZIP tools (no proprietary formats)
44
+ - Human-friendly size specifications (`"100MB"`, `"700MiB"`, `"4.7GB"`)
45
+ - Progress callbacks for large files
46
+ - Context manager support
47
+ - CLI tool included
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install splitzip
53
+ ```
54
+
55
+ ## Quick Start
56
+
57
+ ### Simple Usage
58
+
59
+ ```python
60
+ import splitzip
61
+
62
+ # Create a split archive from files
63
+ splitzip.create(
64
+ "backup.zip",
65
+ ["documents/", "photos/", "important.pdf"],
66
+ split_size="650MB"
67
+ )
68
+ ```
69
+
70
+ Output files: `backup.z01`, `backup.z02`, ..., `backup.zip`
71
+
72
+ ### Context Manager
73
+
74
+ ```python
75
+ from splitzip import SplitZipWriter
76
+
77
+ with SplitZipWriter("backup.zip", split_size="100MB") as zf:
78
+ # Add files
79
+ zf.write("document.pdf")
80
+ zf.write("photos/", recursive=True)
81
+
82
+ # Add with custom name
83
+ zf.write("secret.txt", arcname="data/renamed.txt")
84
+
85
+ # Add content directly
86
+ zf.writestr("hello.txt", b"Hello, World!")
87
+ zf.writestr("config.json", '{"key": "value"}')
88
+ ```
89
+
90
+ ### Advanced Options
91
+
92
+ ```python
93
+ from splitzip import SplitZipWriter, STORED, DEFLATED
94
+
95
+ def on_progress(filename, bytes_done, total_bytes):
96
+ pct = (bytes_done / total_bytes) * 100
97
+ print(f"\r{filename}: {pct:.1f}%", end="")
98
+
99
+ def on_volume(volume_num, path):
100
+ print(f"Created volume: {path}")
101
+
102
+ with SplitZipWriter(
103
+ "backup.zip",
104
+ split_size="700MiB", # DVD size
105
+ compression=DEFLATED, # or STORED for no compression
106
+ compresslevel=9, # 1-9 (default: 6)
107
+ on_volume=on_volume, # Volume creation callback
108
+ on_progress=on_progress, # Progress callback
109
+ ) as zf:
110
+ zf.write("large_file.bin")
111
+ ```
112
+
113
+ ### Streaming from File Objects
114
+
115
+ ```python
116
+ import io
117
+ from splitzip import SplitZipWriter
118
+
119
+ data = get_data_from_somewhere()
120
+
121
+ with SplitZipWriter("archive.zip", split_size="100MB") as zf:
122
+ zf.write_fileobj(
123
+ io.BytesIO(data),
124
+ arcname="streamed.bin",
125
+ size=len(data) # Optional, enables progress callback
126
+ )
127
+ ```
128
+
129
+ ## Size Specifications
130
+
131
+ splitzip accepts sizes in multiple formats:
132
+
133
+ | Format | Example | Bytes |
134
+ |--------|---------|-------|
135
+ | Integer | `104857600` | 104,857,600 |
136
+ | Bytes | `"100B"` | 100 |
137
+ | Kilobytes (decimal) | `"100KB"` | 100,000 |
138
+ | Megabytes (decimal) | `"100MB"` | 100,000,000 |
139
+ | Gigabytes (decimal) | `"4.7GB"` | 4,700,000,000 |
140
+ | Kibibytes (binary) | `"100KiB"` | 102,400 |
141
+ | Mebibytes (binary) | `"700MiB"` | 734,003,200 |
142
+ | Gibibytes (binary) | `"1GiB"` | 1,073,741,824 |
143
+
144
+ Common split sizes:
145
+ - CD-ROM: `"650MB"` or `"700MB"`
146
+ - DVD: `"4.7GB"`
147
+ - FAT32 limit: `"4GiB"` (minus 1 byte)
148
+ - Email attachment: `"25MB"`
149
+
150
+ ## Command Line Interface
151
+
152
+ ```bash
153
+ # Create a split archive
154
+ splitzip create -o backup.zip -s 100MB file1.txt directory/
155
+
156
+ # With options
157
+ splitzip create -o backup.zip -s 700MiB \
158
+ --level 9 \ # Max compression
159
+ --verbose \ # Show progress
160
+ documents/ photos/
161
+
162
+ # Store without compression
163
+ splitzip create -o backup.zip -s 100MB --store largefile.bin
164
+ ```
165
+
166
+ ## Output File Naming
167
+
168
+ splitzip follows the standard ZIP split archive convention:
169
+
170
+ ```
171
+ backup.z01 (first volume)
172
+ backup.z02 (second volume)
173
+ backup.z03 (third volume)
174
+ ...
175
+ backup.zip (final volume, contains central directory)
176
+ ```
177
+
178
+ **All files must be present in the same directory for extraction.**
179
+
180
+ ## Compatibility
181
+
182
+ | Tool | Single Volume | Split Archive |
183
+ |------|:-------------:|:-------------:|
184
+ | Windows Explorer | ✅ | ✅ |
185
+ | WinZip | ✅ | ✅ |
186
+ | 7-Zip | ✅ | ✅ |
187
+ | macOS Archive Utility | ✅ | ✅* |
188
+ | Linux `unzip` | ✅ | ✅** |
189
+ | Python `zipfile` | ✅ | ❌ |
190
+
191
+ \* May require all files to be selected and opened together
192
+ \*\* May require `unzip -F` flag for split archives
193
+
194
+ ## Limitations
195
+
196
+ - **No ZIP64 support yet**: Individual files must be under 4GB, total entries under 65,535
197
+ - **No encryption**: Use filesystem encryption for sensitive data
198
+ - **No reading/extraction**: This is a write-only library (use standard tools to extract)
199
+ - **No ZSTD/LZMA**: Only DEFLATE and STORED compression (for compatibility)
200
+
201
+ ## Development
202
+
203
+ ```bash
204
+ # Clone and install in development mode
205
+ git clone https://github.com/jimothy/splitzip
206
+ cd splitzip
207
+ pip install -e ".[dev]"
208
+
209
+ # Run tests
210
+ pytest
211
+
212
+ # Run with coverage
213
+ pytest --cov=splitzip
214
+
215
+ # Type checking
216
+ mypy src/splitzip
217
+
218
+ # Linting
219
+ ruff check src/splitzip
220
+ ```
221
+
222
+ ## License
223
+
224
+ MIT License. See [LICENSE](LICENSE) for details.
225
+
226
+ ## Contributing
227
+
228
+ Contributions welcome! Please open an issue to discuss major changes before submitting a PR.
@@ -0,0 +1,197 @@
1
+ [![PyPI version](https://badge.fury.io/py/splitzip.svg)](https://pypi.org/project/splitzip/) [![Python versions](https://img.shields.io/pypi/pyversions/splitzip)](https://pypi.org/project/splitzip/) [![License: MIT](https://img.shields.io/pypi/l/splitzip)](https://opensource.org/licenses/MIT)
2
+
3
+ # splitzip
4
+
5
+ Create split ZIP archives compatible with standard tools.
6
+
7
+ **No 7-Zip required.** Archives created with splitzip can be extracted using Windows Explorer, WinZip, macOS Archive Utility, and standard `unzip` on Linux.
8
+
9
+ ## Features
10
+
11
+ - Pure Python, no external dependencies
12
+ - Compatible with standard ZIP tools (no proprietary formats)
13
+ - Human-friendly size specifications (`"100MB"`, `"700MiB"`, `"4.7GB"`)
14
+ - Progress callbacks for large files
15
+ - Context manager support
16
+ - CLI tool included
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install splitzip
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### Simple Usage
27
+
28
+ ```python
29
+ import splitzip
30
+
31
+ # Create a split archive from files
32
+ splitzip.create(
33
+ "backup.zip",
34
+ ["documents/", "photos/", "important.pdf"],
35
+ split_size="650MB"
36
+ )
37
+ ```
38
+
39
+ Output files: `backup.z01`, `backup.z02`, ..., `backup.zip`
40
+
41
+ ### Context Manager
42
+
43
+ ```python
44
+ from splitzip import SplitZipWriter
45
+
46
+ with SplitZipWriter("backup.zip", split_size="100MB") as zf:
47
+ # Add files
48
+ zf.write("document.pdf")
49
+ zf.write("photos/", recursive=True)
50
+
51
+ # Add with custom name
52
+ zf.write("secret.txt", arcname="data/renamed.txt")
53
+
54
+ # Add content directly
55
+ zf.writestr("hello.txt", b"Hello, World!")
56
+ zf.writestr("config.json", '{"key": "value"}')
57
+ ```
58
+
59
+ ### Advanced Options
60
+
61
+ ```python
62
+ from splitzip import SplitZipWriter, STORED, DEFLATED
63
+
64
+ def on_progress(filename, bytes_done, total_bytes):
65
+ pct = (bytes_done / total_bytes) * 100
66
+ print(f"\r{filename}: {pct:.1f}%", end="")
67
+
68
+ def on_volume(volume_num, path):
69
+ print(f"Created volume: {path}")
70
+
71
+ with SplitZipWriter(
72
+ "backup.zip",
73
+ split_size="700MiB", # DVD size
74
+ compression=DEFLATED, # or STORED for no compression
75
+ compresslevel=9, # 1-9 (default: 6)
76
+ on_volume=on_volume, # Volume creation callback
77
+ on_progress=on_progress, # Progress callback
78
+ ) as zf:
79
+ zf.write("large_file.bin")
80
+ ```
81
+
82
+ ### Streaming from File Objects
83
+
84
+ ```python
85
+ import io
86
+ from splitzip import SplitZipWriter
87
+
88
+ data = get_data_from_somewhere()
89
+
90
+ with SplitZipWriter("archive.zip", split_size="100MB") as zf:
91
+ zf.write_fileobj(
92
+ io.BytesIO(data),
93
+ arcname="streamed.bin",
94
+ size=len(data) # Optional, enables progress callback
95
+ )
96
+ ```
97
+
98
+ ## Size Specifications
99
+
100
+ splitzip accepts sizes in multiple formats:
101
+
102
+ | Format | Example | Bytes |
103
+ |--------|---------|-------|
104
+ | Integer | `104857600` | 104,857,600 |
105
+ | Bytes | `"100B"` | 100 |
106
+ | Kilobytes (decimal) | `"100KB"` | 100,000 |
107
+ | Megabytes (decimal) | `"100MB"` | 100,000,000 |
108
+ | Gigabytes (decimal) | `"4.7GB"` | 4,700,000,000 |
109
+ | Kibibytes (binary) | `"100KiB"` | 102,400 |
110
+ | Mebibytes (binary) | `"700MiB"` | 734,003,200 |
111
+ | Gibibytes (binary) | `"1GiB"` | 1,073,741,824 |
112
+
113
+ Common split sizes:
114
+ - CD-ROM: `"650MB"` or `"700MB"`
115
+ - DVD: `"4.7GB"`
116
+ - FAT32 limit: `"4GiB"` (minus 1 byte)
117
+ - Email attachment: `"25MB"`
118
+
119
+ ## Command Line Interface
120
+
121
+ ```bash
122
+ # Create a split archive
123
+ splitzip create -o backup.zip -s 100MB file1.txt directory/
124
+
125
+ # With options
126
+ splitzip create -o backup.zip -s 700MiB \
127
+ --level 9 \ # Max compression
128
+ --verbose \ # Show progress
129
+ documents/ photos/
130
+
131
+ # Store without compression
132
+ splitzip create -o backup.zip -s 100MB --store largefile.bin
133
+ ```
134
+
135
+ ## Output File Naming
136
+
137
+ splitzip follows the standard ZIP split archive convention:
138
+
139
+ ```
140
+ backup.z01 (first volume)
141
+ backup.z02 (second volume)
142
+ backup.z03 (third volume)
143
+ ...
144
+ backup.zip (final volume, contains central directory)
145
+ ```
146
+
147
+ **All files must be present in the same directory for extraction.**
148
+
149
+ ## Compatibility
150
+
151
+ | Tool | Single Volume | Split Archive |
152
+ |------|:-------------:|:-------------:|
153
+ | Windows Explorer | ✅ | ✅ |
154
+ | WinZip | ✅ | ✅ |
155
+ | 7-Zip | ✅ | ✅ |
156
+ | macOS Archive Utility | ✅ | ✅* |
157
+ | Linux `unzip` | ✅ | ✅** |
158
+ | Python `zipfile` | ✅ | ❌ |
159
+
160
+ \* May require all files to be selected and opened together
161
+ \*\* May require `unzip -F` flag for split archives
162
+
163
+ ## Limitations
164
+
165
+ - **No ZIP64 support yet**: Individual files must be under 4GB, total entries under 65,535
166
+ - **No encryption**: Use filesystem encryption for sensitive data
167
+ - **No reading/extraction**: This is a write-only library (use standard tools to extract)
168
+ - **No ZSTD/LZMA**: Only DEFLATE and STORED compression (for compatibility)
169
+
170
+ ## Development
171
+
172
+ ```bash
173
+ # Clone and install in development mode
174
+ git clone https://github.com/jimothy/splitzip
175
+ cd splitzip
176
+ pip install -e ".[dev]"
177
+
178
+ # Run tests
179
+ pytest
180
+
181
+ # Run with coverage
182
+ pytest --cov=splitzip
183
+
184
+ # Type checking
185
+ mypy src/splitzip
186
+
187
+ # Linting
188
+ ruff check src/splitzip
189
+ ```
190
+
191
+ ## License
192
+
193
+ MIT License. See [LICENSE](LICENSE) for details.
194
+
195
+ ## Contributing
196
+
197
+ Contributions welcome! Please open an issue to discuss major changes before submitting a PR.
@@ -0,0 +1,63 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "splitzip"
7
+ version = "0.1.0"
8
+ description = "Create split ZIP archives compatible with standard tools"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.9"
12
+ authors = [
13
+ { name = "twwat", email = "mailto.yourusername@wwwcomdot.com" }
14
+ ]
15
+ keywords = ["zip", "archive", "split", "multipart", "compression", "7z"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Programming Language :: Python :: 3.14",
28
+ "Topic :: System :: Archiving :: Compression",
29
+ ]
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/twwat/splitzip"
33
+ Repository = "https://github.com/twwat/splitzip"
34
+ Issues = "https://github.com/twwat/splitzip/issues"
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=7.0",
39
+ "pytest-cov>=4.0",
40
+ "ruff>=0.1.0",
41
+ "mypy>=1.0",
42
+ ]
43
+
44
+ [project.scripts]
45
+ splitzip = "splitzip.__main__:main"
46
+
47
+ [tool.hatch.build.targets.wheel]
48
+ packages = ["src/splitzip"]
49
+
50
+ [tool.ruff]
51
+ line-length = 100
52
+ target-version = "py39"
53
+
54
+ [tool.ruff.lint]
55
+ select = ["E", "F", "W", "I", "UP", "B", "SIM"]
56
+
57
+ [tool.mypy]
58
+ python_version = "3.9"
59
+ strict = true
60
+
61
+ [tool.pytest.ini_options]
62
+ testpaths = ["tests"]
63
+ addopts = "-v --tb=short"
@@ -0,0 +1,107 @@
1
+ """
2
+ splitzip - Create split ZIP archives compatible with standard tools.
3
+
4
+ Create multi-part ZIP archives that can be extracted with Windows Explorer,
5
+ WinZip, 7-Zip, and other standard tools without requiring special software.
6
+
7
+ Example:
8
+ >>> import splitzip
9
+ >>>
10
+ >>> # Simple one-liner
11
+ >>> splitzip.create("backup.zip", ["file1.txt", "data/"], split_size="100MB")
12
+ >>>
13
+ >>> # Context manager for more control
14
+ >>> with splitzip.SplitZipWriter("backup.zip", split_size="100MB") as zf:
15
+ ... zf.write("file1.txt")
16
+ ... zf.write("data/", recursive=True)
17
+ ... zf.writestr("hello.txt", b"Hello, world!")
18
+
19
+ The resulting files will be named:
20
+ backup.z01, backup.z02, ..., backup.zip
21
+
22
+ The final .zip file contains the central directory and must be present
23
+ along with all .zXX files for extraction.
24
+ """
25
+
26
+ from .exceptions import (
27
+ CompressionError,
28
+ FileNotFoundInArchiveError,
29
+ IntegrityError,
30
+ SplitZipError,
31
+ VolumeTooSmallError,
32
+ VolumeError,
33
+ )
34
+ from .structures import Compression
35
+ from .utils import format_size, parse_size
36
+ from .writer import SplitZipWriter
37
+
38
+ __version__ = "0.1.0"
39
+ __all__ = [
40
+ # Main classes
41
+ "SplitZipWriter",
42
+ # Convenience functions
43
+ "create",
44
+ # Constants
45
+ "Compression",
46
+ "STORED",
47
+ "DEFLATED",
48
+ # Utilities
49
+ "parse_size",
50
+ "format_size",
51
+ # Exceptions
52
+ "SplitZipError",
53
+ "VolumeError",
54
+ "VolumeTooSmallError",
55
+ "CompressionError",
56
+ "IntegrityError",
57
+ "FileNotFoundInArchiveError",
58
+ ]
59
+
60
+ # Convenience aliases
61
+ STORED = Compression.STORED
62
+ DEFLATED = Compression.DEFLATED
63
+
64
+
65
+ def create(
66
+ path: str,
67
+ files: list[str],
68
+ split_size: int | str,
69
+ compression: int = DEFLATED,
70
+ compresslevel: int = 6,
71
+ recursive: bool = True,
72
+ ) -> list[str]:
73
+ """
74
+ Create a split ZIP archive from a list of files/directories.
75
+
76
+ This is a convenience function for simple use cases. For more control,
77
+ use SplitZipWriter directly.
78
+
79
+ Args:
80
+ path: Path for the final .zip file.
81
+ files: List of file/directory paths to include.
82
+ split_size: Maximum size per volume (e.g., "100MB", "700MiB", 104857600).
83
+ compression: Compression method (STORED or DEFLATED).
84
+ compresslevel: DEFLATE compression level 1-9 (default 6).
85
+ recursive: If True, add directory contents recursively.
86
+
87
+ Returns:
88
+ List of paths to all volume files created.
89
+
90
+ Example:
91
+ >>> splitzip.create(
92
+ ... "backup.zip",
93
+ ... ["documents/", "photos/", "important.pdf"],
94
+ ... split_size="650MB" # CD-ROM size
95
+ ... )
96
+ ['backup.z01', 'backup.z02', 'backup.zip']
97
+ """
98
+ with SplitZipWriter(
99
+ path,
100
+ split_size=split_size,
101
+ compression=compression,
102
+ compresslevel=compresslevel,
103
+ ) as zf:
104
+ for file_path in files:
105
+ zf.write(file_path, recursive=recursive)
106
+
107
+ return [str(p) for p in zf.volume_paths]