fastar 0.5.0__cp313-cp313-musllinux_1_2_i686.whl
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.
- fastar/__init__.py +5 -0
- fastar/__init__.pyi +163 -0
- fastar/fastar.cpython-313-i386-linux-musl.so +0 -0
- fastar/py.typed +0 -0
- fastar-0.5.0.dist-info/METADATA +114 -0
- fastar-0.5.0.dist-info/RECORD +9 -0
- fastar-0.5.0.dist-info/WHEEL +4 -0
- fastar-0.5.0.dist-info/licenses/LICENSE +7 -0
- fastar.libs/libgcc_s-27e5a392.so.1 +0 -0
fastar/__init__.py
ADDED
fastar/__init__.pyi
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from os import PathLike
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Literal, Optional, Union, overload
|
|
4
|
+
|
|
5
|
+
from typing_extensions import Self
|
|
6
|
+
|
|
7
|
+
class FastarError(Exception):
|
|
8
|
+
"""Base exception for all fastar errors."""
|
|
9
|
+
|
|
10
|
+
class ArchiveClosedError(FastarError):
|
|
11
|
+
"""Exception raised when attempting to use a closed archive."""
|
|
12
|
+
|
|
13
|
+
class ArchiveUnpackingError(FastarError):
|
|
14
|
+
"""Exception raised when unpacking an archive fails."""
|
|
15
|
+
|
|
16
|
+
class ArchiveAppendingError(FastarError):
|
|
17
|
+
"""Exception raised when appending to an archive fails."""
|
|
18
|
+
|
|
19
|
+
class NameDerivationError(ArchiveAppendingError):
|
|
20
|
+
"""Exception raised when a file name cannot be derived from a path."""
|
|
21
|
+
|
|
22
|
+
class ArchiveWriter:
|
|
23
|
+
"""A tar archive writer that supports compressed and uncompressed formats."""
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def open(
|
|
27
|
+
cls, path: Union[str, Path, PathLike[str]], mode: Literal["w", "w:gz"] = "w:gz"
|
|
28
|
+
) -> Self:
|
|
29
|
+
"""
|
|
30
|
+
Open a tar archive for writing.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
path: Path to the archive file to create
|
|
34
|
+
mode: Write mode - 'w' for uncompressed, 'w:gz' for gzip compressed (default)
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
An ArchiveWriter instance
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
ValueError: If an unsupported mode is provided
|
|
41
|
+
OSError: If the file cannot be opened
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def append(
|
|
45
|
+
self,
|
|
46
|
+
path: Union[str, Path, PathLike[str]],
|
|
47
|
+
arcname: Optional[Union[str, Path, PathLike[str]]] = None,
|
|
48
|
+
recursive: bool = True,
|
|
49
|
+
dereference: bool = False,
|
|
50
|
+
) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Append a file or directory to the archive.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
path: Path to the file or directory to append
|
|
56
|
+
arcname: Name to use in the archive (defaults to the filename)
|
|
57
|
+
recursive: If True and path is a directory, append all contents recursively
|
|
58
|
+
dereference: If True, append the target of symlinks instead of the symlink itself
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
ArchiveClosedError: If the archive is already closed
|
|
62
|
+
ArchiveAppendingError: If the target cannot be appended to the archive
|
|
63
|
+
OSError: If there's an error reading the target file or directory
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def close(self) -> None:
|
|
67
|
+
"""
|
|
68
|
+
Close the archive and flush all pending writes.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
OSError: If there's an error flushing the archive
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __enter__(self) -> Self:
|
|
75
|
+
"""Enter the context manager."""
|
|
76
|
+
|
|
77
|
+
def __exit__(self, exc_type, exc_value, traceback) -> bool:
|
|
78
|
+
"""Exit the context manager, closing the archive."""
|
|
79
|
+
|
|
80
|
+
class ArchiveReader:
|
|
81
|
+
"""A tar archive reader that supports compressed and uncompressed formats."""
|
|
82
|
+
|
|
83
|
+
@classmethod
|
|
84
|
+
def open(
|
|
85
|
+
cls, path: Union[str, Path, PathLike[str]], mode: Literal["r", "r:gz"] = "r:gz"
|
|
86
|
+
) -> Self:
|
|
87
|
+
"""
|
|
88
|
+
Open a tar archive for reading.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
path: Path to the archive file to read
|
|
92
|
+
mode: Read mode - 'r' for uncompressed, 'r:gz' for gzip compressed (default)
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
An ArchiveReader instance
|
|
96
|
+
|
|
97
|
+
Raises:
|
|
98
|
+
ValueError: If an unsupported mode is provided
|
|
99
|
+
OSError: If the file cannot be opened
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def unpack(
|
|
103
|
+
self, to: Union[str, Path, PathLike[str]], preserve_mtime: bool = True
|
|
104
|
+
) -> None:
|
|
105
|
+
"""
|
|
106
|
+
Unpack all contents of the archive and put them into the specified directory.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
to: Destination directory path
|
|
110
|
+
preserve_mtime: whether to preserve file modification times
|
|
111
|
+
|
|
112
|
+
Raises:
|
|
113
|
+
ArchiveClosedError: If the archive is already closed
|
|
114
|
+
ArchiveUnpackingError: If the archive cannot be unpacked
|
|
115
|
+
OSError: If unpacking fails due to I/O errors
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
def close(self) -> None:
|
|
119
|
+
"""Close the archive."""
|
|
120
|
+
|
|
121
|
+
def __enter__(self) -> Self:
|
|
122
|
+
"""Enter the context manager."""
|
|
123
|
+
|
|
124
|
+
def __exit__(self, exc_type, exc_value, traceback) -> bool:
|
|
125
|
+
"""Exit the context manager, closing the archive."""
|
|
126
|
+
|
|
127
|
+
@overload
|
|
128
|
+
def open(
|
|
129
|
+
path: Union[str, Path, PathLike[str]], mode: Literal["w", "w:gz"]
|
|
130
|
+
) -> ArchiveWriter:
|
|
131
|
+
"""
|
|
132
|
+
Open a tar archive for writing.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
path: Path to the archive file to create
|
|
136
|
+
mode: Write mode - 'w' for uncompressed, 'w:gz' for gzip compressed
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
An ArchiveWriter instance
|
|
140
|
+
|
|
141
|
+
Raises:
|
|
142
|
+
ValueError: If an unsupported mode is provided
|
|
143
|
+
OSError: If the file cannot be opened
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
@overload
|
|
147
|
+
def open(
|
|
148
|
+
path: Union[str, Path, PathLike[str]], mode: Literal["r", "r:gz"]
|
|
149
|
+
) -> ArchiveReader:
|
|
150
|
+
"""
|
|
151
|
+
Open a tar archive for reading.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
path: Path to the archive file to read
|
|
155
|
+
mode: Read mode - 'r' for uncompressed, 'r:gz' for gzip compressed
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
An ArchiveReader instance
|
|
159
|
+
|
|
160
|
+
Raises:
|
|
161
|
+
ValueError: If an unsupported mode is provided
|
|
162
|
+
OSError: If the file cannot be opened
|
|
163
|
+
"""
|
|
Binary file
|
fastar/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastar
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Classifier: Intended Audience :: Developers
|
|
5
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
6
|
+
Classifier: Operating System :: OS Independent
|
|
7
|
+
Classifier: Programming Language :: Rust
|
|
8
|
+
Classifier: Programming Language :: Python
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
18
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Summary: High-level bindings for the Rust tar crate
|
|
23
|
+
Author-email: Jonathan Ehwald <github@ehwald.info>
|
|
24
|
+
License-Expression: MIT
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
27
|
+
Project-URL: homepage, https://github.com/DoctorJohn/fastar
|
|
28
|
+
Project-URL: repository, https://github.com/DoctorJohn/fastar
|
|
29
|
+
Project-URL: documentation, https://github.com/DoctorJohn/fastar
|
|
30
|
+
|
|
31
|
+
# Fastar
|
|
32
|
+
|
|
33
|
+
[![Versions][versions-image]][versions-url]
|
|
34
|
+
[![PyPI][pypi-image]][pypi-url]
|
|
35
|
+
[![Downloads][downloads-image]][downloads-url]
|
|
36
|
+
[![License][license-image]][license-url]
|
|
37
|
+
[![CodSpeed][codspeed-image]][codspeed-url]
|
|
38
|
+
|
|
39
|
+
[versions-image]: https://img.shields.io/pypi/pyversions/fastar
|
|
40
|
+
[versions-url]: https://github.com/DoctorJohn/fastar/blob/main/pyproject.toml
|
|
41
|
+
[pypi-image]: https://img.shields.io/pypi/v/fastar
|
|
42
|
+
[pypi-url]: https://pypi.org/project/fastar/
|
|
43
|
+
[downloads-image]: https://img.shields.io/pypi/dm/fastar
|
|
44
|
+
[downloads-url]: https://pypi.org/project/fastar/
|
|
45
|
+
[license-image]: https://img.shields.io/pypi/l/fastar
|
|
46
|
+
[license-url]: https://github.com/DoctorJohn/fastar/blob/main/LICENSE
|
|
47
|
+
[codspeed-image]: https://img.shields.io/endpoint?url=https://codspeed.io/badge.json
|
|
48
|
+
[codspeed-url]: https://codspeed.io/DoctorJohn/fastar
|
|
49
|
+
|
|
50
|
+
The `fastar` library wraps the Rust [tar](https://crates.io/crates/tar) and [flate2](https://crates.io/crates/flate2) crates, providing a high-performance way to work with compressed and uncompressed tar archives in Python.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
pip install fastar
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
This section shows basic examples of how to create and extract tar archives using Fastar. For more usage examples, please refer directly to the test cases in the [tests](https://github.com/DoctorJohn/fastar/tree/main/tests) directory.
|
|
61
|
+
|
|
62
|
+
### Working with uncompressed tar archives
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import fastar
|
|
66
|
+
from pathlib import Path
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
input_file = Path("file.txt")
|
|
70
|
+
input_file.write_text("Hello, Fastar!")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
with fastar.open("archive.tar", "w") as archive:
|
|
74
|
+
archive.append(input_file)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
with fastar.open("archive.tar", "r") as archive:
|
|
78
|
+
archive.unpack("output/")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
unpacked_file = Path("output/file.txt")
|
|
82
|
+
print(unpacked_file.read_text()) # Hello, Fastar!
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Working with gzip-compressed tar archives
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import fastar
|
|
89
|
+
from pathlib import Path
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
input_file = Path("file.txt")
|
|
93
|
+
input_file.write_text("Hello, Fastar!")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
with fastar.open("archive.tar.gz", "w:gz") as archive:
|
|
97
|
+
archive.append(input_file)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
with fastar.open("archive.tar.gz", "r:gz") as archive:
|
|
101
|
+
archive.unpack("output/")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
unpacked_file = Path("output/file.txt")
|
|
105
|
+
print(unpacked_file.read_text()) # Hello, Fastar!
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Development
|
|
109
|
+
|
|
110
|
+
1. Install dependencies into a virtual env: `uv sync`
|
|
111
|
+
2. Make changes to the code and tests
|
|
112
|
+
3. Build the package: `uv run maturin develop`
|
|
113
|
+
4. Run the tests: `uv run pytest`
|
|
114
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
fastar-0.5.0.dist-info/METADATA,sha256=LrUR4goV7xjxI-HAQRqr3U9WfsdC66BktJIXwP0wBXk,3779
|
|
2
|
+
fastar-0.5.0.dist-info/WHEEL,sha256=a6I402lte9iftsl1URPLE2091PrRf96YDg6D4Buckgw,106
|
|
3
|
+
fastar-0.5.0.dist-info/licenses/LICENSE,sha256=rYGQpMiiUoV5IPve_SRv0E-Ci8BMj0TaNs5jSu3d6xo,1054
|
|
4
|
+
fastar.libs/libgcc_s-27e5a392.so.1,sha256=x5sO63liVwXxrjGGP371wB0RyQe1KEnIynYm82T0G0M,449745
|
|
5
|
+
fastar/__init__.py,sha256=mU2iZJ--coorw9PWKBK1JbU9C_N5EqCZQ-b7YvPFBWw,107
|
|
6
|
+
fastar/__init__.pyi,sha256=mukg31ozAocMs0y2B1XUBI2OCzCuNSzRNzMFNzMelGo,4952
|
|
7
|
+
fastar/fastar.cpython-313-i386-linux-musl.so,sha256=vvRbEgbkSgXwyMoK5aiQXfduZWSYlFPTBFYr7_qd8oo,949037
|
|
8
|
+
fastar/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
fastar-0.5.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 Jonathan Ehwald
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Binary file
|