0
# Safer
1
2
A safer writer for files and streams that prevents corruption and partial writes through atomic operations. Safer provides drop-in replacements for Python's built-in file operations, ensuring that either complete data is written or the original file remains unchanged.
3
4
## Package Information
5
6
- **Package Name**: safer
7
- **Language**: Python
8
- **Installation**: `pip install safer`
9
10
## Core Imports
11
12
```python
13
import safer
14
```
15
16
All functions are available directly from the `safer` module:
17
18
```python
19
from safer import open, writer, closer, dump, printer
20
```
21
22
## Basic Usage
23
24
```python
25
import safer
26
import json
27
28
# Safe file writing - either complete or nothing
29
with safer.open('data.json', 'w') as fp:
30
json.dump({"key": "value"}, fp)
31
# If an exception occurs here, data.json remains unchanged
32
33
# Safe stream wrapping
34
import socket
35
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
36
with safer.writer(sock) as s:
37
s.write(b"header\n")
38
s.write(b"body\n") # If exception occurs, nothing is sent to socket
39
s.write(b"footer\n")
40
41
# Safe printing to file
42
with safer.printer('output.txt', 'w') as print_func:
43
for item in data:
44
print_func(item) # Either all items printed or file unchanged
45
```
46
47
## Capabilities
48
49
### File Opening
50
51
Drop-in replacement for Python's built-in `open()` function that provides atomic file writing operations.
52
53
```python { .api }
54
def open(
55
name: Path | str,
56
mode: str = 'r',
57
buffering: int = -1,
58
encoding: str | None = None,
59
errors: str | None = None,
60
newline: str | None = None,
61
closefd: bool = True,
62
opener: t.Callable | None = None,
63
make_parents: bool = False,
64
delete_failures: bool = True,
65
temp_file: bool = False,
66
dry_run: bool | t.Callable = False,
67
enabled: bool = True,
68
) -> t.IO:
69
"""
70
Safe file opening with atomic write operations.
71
72
Parameters:
73
- name: File path to open
74
- mode: File open mode (same as built-in open)
75
- buffering: Buffer size (-1 for default)
76
- encoding: Text encoding for text mode
77
- errors: Error handling strategy
78
- newline: Newline handling
79
- closefd: Whether to close file descriptor
80
- opener: Custom opener function
81
- make_parents: Create parent directories if needed
82
- delete_failures: Delete temporary files on failure
83
- temp_file: Use disk temporary file instead of memory buffer
84
- dry_run: Test mode - don't actually write (bool) or pass data to callable
85
- enabled: Enable/disable safer functionality
86
87
Returns:
88
File-like object that writes atomically
89
"""
90
```
91
92
### Stream Writing
93
94
Wraps existing streams, sockets, or callables to provide safe writing operations that only commit on successful completion.
95
96
```python { .api }
97
def writer(
98
stream: t.Callable | None | t.IO | Path | str = None,
99
is_binary: bool | None = None,
100
close_on_exit: bool = False,
101
temp_file: bool = False,
102
chunk_size: int = 0x100000,
103
delete_failures: bool = True,
104
dry_run: bool | t.Callable = False,
105
enabled: bool = True,
106
) -> t.Callable | t.IO:
107
"""
108
Write safely to file streams, sockets and callables.
109
110
Parameters:
111
- stream: Target stream, socket, callable, or file path (None for sys.stdout)
112
- is_binary: Whether stream is binary (auto-detected if None)
113
- close_on_exit: Close underlying stream when writer closes
114
- temp_file: Use disk temporary file (bool or custom path)
115
- chunk_size: Chunk size for temporary file transfers
116
- delete_failures: Delete temporary files on failure
117
- dry_run: Test mode - don't write (bool) or pass data to callable
118
- enabled: Enable/disable safer functionality
119
120
Returns:
121
Wrapped stream that writes atomically
122
"""
123
```
124
125
### Stream Closing
126
127
Like `writer()` but with automatic closing of the underlying stream enabled by default.
128
129
```python { .api }
130
def closer(
131
stream: t.IO,
132
is_binary: bool | None = None,
133
close_on_exit: bool = True,
134
**kwds
135
) -> t.Callable | t.IO:
136
"""
137
Safe stream wrapper with automatic closing.
138
139
Parameters:
140
- stream: Stream to wrap
141
- is_binary: Whether stream is binary (auto-detected if None)
142
- close_on_exit: Close underlying stream when done (default True)
143
- **kwds: Additional arguments passed to writer()
144
145
Returns:
146
Wrapped stream with automatic closing
147
"""
148
```
149
150
### Data Serialization
151
152
Safe serialization using json.dump or other serialization protocols with atomic write operations.
153
154
```python { .api }
155
def dump(
156
obj,
157
stream: t.Callable | None | t.IO | Path | str = None,
158
dump: t.Any = None,
159
**kwargs,
160
) -> t.Any:
161
"""
162
Safely serialize objects to streams or files.
163
164
Parameters:
165
- obj: Object to serialize
166
- stream: Target stream, file path, or None for sys.stdout
167
- dump: Serialization function/module (defaults to json.dump)
168
Can be 'json', 'yaml', 'toml' or callable
169
- **kwargs: Additional arguments passed to dump function
170
171
Returns:
172
Result from the dump function
173
"""
174
```
175
176
### File Printing
177
178
Context manager that yields a print function for safe file writing, ensuring atomic operations.
179
180
```python { .api }
181
def printer(
182
name: Path | str,
183
mode: str = 'w',
184
*args,
185
**kwargs
186
) -> t.Iterator[t.Callable]:
187
"""
188
Context manager for safe printing to files.
189
190
Parameters:
191
- name: File path
192
- mode: File open mode (must support writing)
193
- *args, **kwargs: Additional arguments passed to safer.open()
194
195
Yields:
196
Print function that writes to the opened file
197
198
Usage:
199
with safer.printer('output.txt', 'w') as print_func:
200
print_func("Line 1")
201
print_func("Line 2")
202
"""
203
```
204
205
## Types
206
207
```python { .api }
208
from pathlib import Path
209
from typing import IO, Callable, Any, Iterator
210
211
# Common type aliases used throughout the API
212
StreamType = Callable | None | IO | Path | str
213
DumpFunction = str | Callable | Any
214
FileMode = str # e.g., 'r', 'w', 'a', 'rb', 'wb', 'r+', etc.
215
PrintFunction = Callable[..., None] # Function returned by printer()
216
```
217
218
## Safety Features
219
220
### Atomic Operations
221
- **All-or-nothing writes**: Files are either completely written or left unchanged
222
- **Exception safety**: Automatic rollback on any failure during writing
223
- **Temporary file handling**: Automatic cleanup of temporary files on errors
224
225
### Writing Strategies
226
- **Memory buffering**: Default strategy using StringIO/BytesIO for smaller data
227
- **Temporary files**: Disk-based strategy for large files using os.replace()
228
- **Stream wrapping**: Safe writing to sockets, callables, and existing streams
229
230
### Testing and Development
231
- **Dry run mode**: Test writing operations without modifying files
232
- **Callable dry run**: Pass written data to custom functions for testing
233
- **Parent directory creation**: Automatic creation of missing parent directories
234
- **Failure handling**: Configurable temporary file cleanup and error reporting
235
236
### Configuration Options
237
- **Binary/text mode detection**: Automatic detection or explicit specification
238
- **Buffering control**: Configurable buffer sizes and strategies
239
- **Custom openers**: Support for custom file opening functions
240
- **Enable/disable**: Runtime control of safer functionality