0
# Path and File Management
1
2
File path handling and package file enumeration, including path objects, file hashing, and file access methods for package contents. This system provides comprehensive access to files within installed packages.
3
4
## Capabilities
5
6
### PackagePath Class
7
8
Path objects representing files within package distributions:
9
10
```python { .api }
11
class PackagePath(pathlib.PurePosixPath):
12
"""
13
A reference to a path in a package.
14
15
Extends pathlib.PurePosixPath to provide package-specific file operations
16
with metadata about file hashes and sizes.
17
"""
18
19
hash: FileHash | None # File hash information (optional)
20
size: int # File size in bytes
21
dist: Distribution # Associated distribution
22
23
def read_text(self, encoding: str = 'utf-8') -> str:
24
"""
25
Read the file as text.
26
27
Parameters:
28
- encoding: Text encoding (default: 'utf-8')
29
30
Returns:
31
str: File contents as text
32
"""
33
34
def read_binary(self) -> bytes:
35
"""
36
Read the file as binary data.
37
38
Returns:
39
bytes: File contents as bytes
40
"""
41
42
def locate(self) -> SimplePath:
43
"""
44
Return a path-like object for this path.
45
46
Returns:
47
SimplePath: A path object that can be used to access the actual file
48
"""
49
```
50
51
#### Usage Examples
52
53
```python
54
import importlib_metadata
55
56
# Get files for a package
57
files = importlib_metadata.files('requests')
58
if files:
59
for file_path in files[:5]: # Show first 5 files
60
print(f"File: {file_path}")
61
print(f" Size: {file_path.size} bytes")
62
if file_path.hash:
63
print(f" Hash: {file_path.hash.mode}={file_path.hash.value}")
64
65
# Read file contents (for text files)
66
if file_path.suffix == '.py':
67
try:
68
content = file_path.read_text()
69
print(f" Content preview: {content[:100]}...")
70
except Exception as e:
71
print(f" Could not read: {e}")
72
73
# Get actual file location
74
actual_path = file_path.locate()
75
print(f" Located at: {actual_path}")
76
```
77
78
### FileHash Class
79
80
File hash information for integrity verification:
81
82
```python { .api }
83
class FileHash:
84
"""
85
File hash information for package files.
86
87
Provides hash algorithm and value for file integrity verification.
88
"""
89
90
mode: str # Hash algorithm (e.g., 'sha256', 'md5')
91
value: str # Hash value as hexadecimal string
92
93
def __init__(self, spec: str) -> None:
94
"""
95
Initialize from hash specification string.
96
97
Parameters:
98
- spec: Hash specification in format 'algorithm=value' (e.g., 'sha256=abc123...')
99
"""
100
101
def __repr__(self) -> str:
102
"""
103
String representation of the file hash.
104
105
Returns:
106
str: Representation showing hash mode and value
107
"""
108
```
109
110
#### Usage Examples
111
112
```python
113
import importlib_metadata
114
115
# Find files with hashes
116
files = importlib_metadata.files('requests')
117
if files:
118
hashed_files = [f for f in files if f.hash]
119
print(f"Found {len(hashed_files)} files with hash information")
120
121
for file_path in hashed_files[:3]: # Show first 3
122
hash_info = file_path.hash
123
print(f"File: {file_path}")
124
print(f" Hash algorithm: {hash_info.mode}")
125
print(f" Hash value: {hash_info.value[:16]}...") # Show first 16 chars
126
```
127
128
### SimplePath Protocol
129
130
Protocol interface for path-like objects used throughout the library:
131
132
```python { .api }
133
class SimplePath(Protocol):
134
"""
135
A minimal subset of pathlib.Path required by Distribution.
136
137
Defines the interface that path objects must implement to work
138
with the importlib_metadata system.
139
"""
140
141
def joinpath(self, other: str | os.PathLike[str]) -> SimplePath:
142
"""
143
Join this path with another path component.
144
145
Parameters:
146
- other: Path component to join
147
148
Returns:
149
SimplePath: New path with component joined
150
"""
151
152
def __truediv__(self, other: str | os.PathLike[str]) -> SimplePath:
153
"""
154
Path division operator (/).
155
156
Parameters:
157
- other: Path component to join
158
159
Returns:
160
SimplePath: New path with component joined
161
"""
162
163
@property
164
def parent(self) -> SimplePath:
165
"""
166
Return the parent directory of this path.
167
168
Returns:
169
SimplePath: Parent directory path
170
"""
171
172
def read_text(self, encoding=None) -> str:
173
"""
174
Read the file as text.
175
176
Parameters:
177
- encoding: Text encoding (optional)
178
179
Returns:
180
str: File contents as text
181
"""
182
183
def read_bytes(self) -> bytes:
184
"""
185
Read the file as binary data.
186
187
Returns:
188
bytes: File contents as bytes
189
"""
190
191
def exists(self) -> bool:
192
"""
193
Check if the path exists.
194
195
Returns:
196
bool: True if path exists
197
"""
198
```
199
200
### File Enumeration and Filtering
201
202
Working with package file collections:
203
204
#### Usage Examples
205
206
```python
207
import importlib_metadata
208
209
# Get all files for a package
210
files = importlib_metadata.files('requests')
211
if files:
212
print(f"Total files: {len(files)}")
213
214
# Filter by file type
215
py_files = [f for f in files if f.suffix == '.py']
216
print(f"Python files: {len(py_files)}")
217
218
# Filter by directory
219
lib_files = [f for f in files if 'requests' in f.parts]
220
print(f"Files in requests directory: {len(lib_files)}")
221
222
# Find specific files
223
init_files = [f for f in files if f.name == '__init__.py']
224
print(f"__init__.py files: {len(init_files)}")
225
226
# Files with specific extensions
227
data_files = [f for f in files if f.suffix in ['.txt', '.rst', '.md']]
228
print(f"Documentation files: {len(data_files)}")
229
230
# Large files
231
large_files = [f for f in files if f.size > 10000] # > 10KB
232
print(f"Large files (>10KB): {len(large_files)}")
233
```
234
235
### File Content Access
236
237
Reading and processing package files:
238
239
```python
240
import importlib_metadata
241
242
# Get package files
243
files = importlib_metadata.files('requests')
244
if files:
245
# Read text files
246
for file_path in files:
247
if file_path.name == 'MANIFEST.in':
248
try:
249
content = file_path.read_text()
250
print(f"MANIFEST.in content:\n{content}")
251
break
252
except Exception as e:
253
print(f"Could not read MANIFEST.in: {e}")
254
255
# Read binary files
256
for file_path in files:
257
if file_path.suffix == '.whl': # If any wheel files
258
try:
259
data = file_path.read_binary()
260
print(f"Binary file {file_path.name}: {len(data)} bytes")
261
break
262
except Exception as e:
263
print(f"Could not read binary file: {e}")
264
265
# Check file existence
266
for file_path in files[:5]:
267
actual_path = file_path.locate()
268
exists = actual_path.exists()
269
print(f"File {file_path.name} exists: {exists}")
270
```
271
272
### File System Integration
273
274
Working with actual file system paths:
275
276
```python
277
import importlib_metadata
278
from pathlib import Path
279
280
# Get distribution and locate files
281
dist = importlib_metadata.distribution('requests')
282
files = dist.files
283
if files:
284
# Get actual file system paths
285
for file_path in files[:3]:
286
actual_path = file_path.locate()
287
288
# Convert to pathlib.Path if needed
289
if hasattr(actual_path, 'resolve'):
290
resolved = actual_path.resolve()
291
print(f"File: {file_path}")
292
print(f" Actual path: {resolved}")
293
print(f" Exists: {resolved.exists()}")
294
```
295
296
## Error Handling
297
298
File operations can raise various exceptions:
299
300
```python
301
import importlib_metadata
302
303
files = importlib_metadata.files('requests')
304
if files:
305
file_path = files[0]
306
307
# Handle file reading errors
308
try:
309
content = file_path.read_text()
310
except UnicodeDecodeError:
311
print("File is not valid text")
312
content = file_path.read_binary()
313
except FileNotFoundError:
314
print("File not found on filesystem")
315
except PermissionError:
316
print("Permission denied")
317
318
# Handle path location errors
319
try:
320
actual_path = file_path.locate()
321
except NotImplementedError:
322
print("Distribution doesn't support file location")
323
```