0
# File Handling
1
2
Specialized file type classes for handling different types of file I/O operations in CLI applications. These classes provide type hints and specialized behavior for file parameters.
3
4
## Capabilities
5
6
### Text File Types
7
8
File type classes for handling text files with different access modes.
9
10
```python { .api }
11
class FileText(io.TextIOWrapper):
12
"""
13
Text file type for reading text files.
14
15
This class extends io.TextIOWrapper and is used as a type hint
16
for CLI parameters that should accept text files for reading.
17
"""
18
19
class FileTextWrite(FileText):
20
"""
21
Text file type for writing text files.
22
23
This class extends FileText and is used as a type hint
24
for CLI parameters that should accept text files for writing.
25
"""
26
```
27
28
### Binary File Types
29
30
File type classes for handling binary files with different access modes.
31
32
```python { .api }
33
class FileBinaryRead(io.BufferedReader):
34
"""
35
Binary file type for reading binary files.
36
37
This class extends io.BufferedReader and is used as a type hint
38
for CLI parameters that should accept binary files for reading.
39
"""
40
41
class FileBinaryWrite(io.BufferedWriter):
42
"""
43
Binary file type for writing binary files.
44
45
This class extends io.BufferedWriter and is used as a type hint
46
for CLI parameters that should accept binary files for writing.
47
"""
48
```
49
50
## Usage Examples
51
52
### Text File Processing
53
54
```python
55
import typer
56
from typer import FileText, FileTextWrite
57
58
def process_text(
59
input_file: FileText = typer.Argument(..., help="Input text file"),
60
output_file: FileTextWrite = typer.Option("output.txt", "--output", "-o", help="Output text file")
61
):
62
"""Process a text file and write results to another text file."""
63
content = input_file.read()
64
processed = content.upper() # Example processing
65
output_file.write(processed)
66
67
typer.echo(f"Processed {input_file.name} -> {output_file.name}")
68
69
if __name__ == "__main__":
70
typer.run(process_text)
71
```
72
73
### Binary File Operations
74
75
```python
76
import typer
77
from typer import FileBinaryRead, FileBinaryWrite
78
79
def copy_binary(
80
source: FileBinaryRead = typer.Argument(..., help="Source binary file"),
81
dest: FileBinaryWrite = typer.Argument(..., help="Destination binary file")
82
):
83
"""Copy a binary file to another location."""
84
while True:
85
chunk = source.read(8192) # Read in 8KB chunks
86
if not chunk:
87
break
88
dest.write(chunk)
89
90
typer.echo(f"Copied {source.name} -> {dest.name}")
91
92
if __name__ == "__main__":
93
typer.run(copy_binary)
94
```
95
96
### File Type with Standard Input/Output
97
98
```python
99
import typer
100
import sys
101
from typer import FileText, FileTextWrite
102
103
def filter_lines(
104
input_file: FileText = typer.Option(sys.stdin, "--input", "-i", help="Input file (default: stdin)"),
105
output_file: FileTextWrite = typer.Option(sys.stdout, "--output", "-o", help="Output file (default: stdout)"),
106
pattern: str = typer.Option("", "--pattern", "-p", help="Pattern to filter")
107
):
108
"""Filter lines from input file that contain the pattern."""
109
for line in input_file:
110
if pattern in line:
111
output_file.write(line)
112
113
if __name__ == "__main__":
114
typer.run(filter_lines)
115
```
116
117
### File Processing with Context Management
118
119
```python
120
import typer
121
from pathlib import Path
122
from typer import FileText, FileTextWrite
123
from typing import Optional
124
125
def merge_files(
126
files: list[Path] = typer.Argument(..., help="Files to merge"),
127
output: Optional[FileTextWrite] = typer.Option(None, "--output", "-o", help="Output file")
128
):
129
"""Merge multiple text files into one."""
130
output_file = output or sys.stdout
131
132
for file_path in files:
133
with open(file_path, 'r') as f:
134
content = f.read()
135
output_file.write(f"=== {file_path} ===\n")
136
output_file.write(content)
137
output_file.write("\n\n")
138
139
if output:
140
typer.echo(f"Merged {len(files)} files to {output.name}")
141
else:
142
typer.echo(f"Merged {len(files)} files to stdout")
143
144
if __name__ == "__main__":
145
typer.run(merge_files)
146
```
147
148
### File Encoding and Error Handling
149
150
```python
151
import typer
152
from typer import FileText, FileTextWrite
153
154
def convert_encoding(
155
input_file: FileText = typer.Argument(..., help="Input file"),
156
output_file: FileTextWrite = typer.Argument(..., help="Output file"),
157
input_encoding: str = typer.Option("utf-8", help="Input file encoding"),
158
output_encoding: str = typer.Option("utf-8", help="Output file encoding")
159
):
160
"""Convert file encoding."""
161
try:
162
# Read with specified input encoding
163
with open(input_file.name, 'r', encoding=input_encoding) as f:
164
content = f.read()
165
166
# Write with specified output encoding
167
with open(output_file.name, 'w', encoding=output_encoding) as f:
168
f.write(content)
169
170
typer.echo(f"Converted {input_file.name} from {input_encoding} to {output_encoding}")
171
172
except UnicodeDecodeError as e:
173
typer.echo(f"Error reading file with {input_encoding} encoding: {e}", err=True)
174
raise typer.Exit(1)
175
except UnicodeEncodeError as e:
176
typer.echo(f"Error writing file with {output_encoding} encoding: {e}", err=True)
177
raise typer.Exit(1)
178
179
if __name__ == "__main__":
180
typer.run(convert_encoding)
181
```
182
183
### Advanced File Parameter Configuration
184
185
```python
186
import typer
187
from pathlib import Path
188
from typer import FileText, FileTextWrite
189
190
def process_config(
191
config_file: FileText = typer.Option(
192
...,
193
"--config", "-c",
194
exists=True,
195
readable=True,
196
help="Configuration file"
197
),
198
output_file: FileTextWrite = typer.Option(
199
"result.txt",
200
"--output", "-o",
201
writable=True,
202
help="Output file"
203
),
204
log_file: FileTextWrite = typer.Option(
205
None,
206
"--log",
207
writable=True,
208
help="Log file (optional)"
209
)
210
):
211
"""Process configuration with file validation."""
212
import json
213
214
try:
215
config = json.load(config_file)
216
typer.echo(f"Loaded config from {config_file.name}")
217
218
# Process configuration
219
result = {"processed": True, "config": config}
220
json.dump(result, output_file, indent=2)
221
222
if log_file:
223
from datetime import datetime
224
log_file.write(f"Processed config at {datetime.now()}\n")
225
226
except json.JSONDecodeError as e:
227
typer.echo(f"Invalid JSON in config file: {e}", err=True)
228
raise typer.Exit(1)
229
230
if __name__ == "__main__":
231
typer.run(process_config)
232
```
233
234
### Streaming File Processing
235
236
```python
237
import typer
238
from typer import FileText, FileTextWrite
239
240
def process_large_file(
241
input_file: FileText = typer.Argument(..., help="Large input file"),
242
output_file: FileTextWrite = typer.Argument(..., help="Output file"),
243
chunk_size: int = typer.Option(1024, help="Processing chunk size")
244
):
245
"""Process large files in chunks to manage memory."""
246
processed_lines = 0
247
248
while True:
249
lines = input_file.readlines(chunk_size)
250
if not lines:
251
break
252
253
# Process chunk
254
processed_chunk = ''.join(line.strip() + '\n' for line in lines if line.strip())
255
output_file.write(processed_chunk)
256
257
processed_lines += len(lines)
258
if processed_lines % 1000 == 0:
259
typer.echo(f"Processed {processed_lines} lines...")
260
261
typer.echo(f"Processing complete. Total lines: {processed_lines}")
262
263
if __name__ == "__main__":
264
typer.run(process_large_file)
265
```