Read metadata from Python packages, providing third-party access to importlib.metadata functionality
—
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.
Path objects representing files within package distributions:
class PackagePath(pathlib.PurePosixPath):
"""
A reference to a path in a package.
Extends pathlib.PurePosixPath to provide package-specific file operations
with metadata about file hashes and sizes.
"""
hash: FileHash | None # File hash information (optional)
size: int # File size in bytes
dist: Distribution # Associated distribution
def read_text(self, encoding: str = 'utf-8') -> str:
"""
Read the file as text.
Parameters:
- encoding: Text encoding (default: 'utf-8')
Returns:
str: File contents as text
"""
def read_binary(self) -> bytes:
"""
Read the file as binary data.
Returns:
bytes: File contents as bytes
"""
def locate(self) -> SimplePath:
"""
Return a path-like object for this path.
Returns:
SimplePath: A path object that can be used to access the actual file
"""import importlib_metadata
# Get files for a package
files = importlib_metadata.files('requests')
if files:
for file_path in files[:5]: # Show first 5 files
print(f"File: {file_path}")
print(f" Size: {file_path.size} bytes")
if file_path.hash:
print(f" Hash: {file_path.hash.mode}={file_path.hash.value}")
# Read file contents (for text files)
if file_path.suffix == '.py':
try:
content = file_path.read_text()
print(f" Content preview: {content[:100]}...")
except Exception as e:
print(f" Could not read: {e}")
# Get actual file location
actual_path = file_path.locate()
print(f" Located at: {actual_path}")File hash information for integrity verification:
class FileHash:
"""
File hash information for package files.
Provides hash algorithm and value for file integrity verification.
"""
mode: str # Hash algorithm (e.g., 'sha256', 'md5')
value: str # Hash value as hexadecimal string
def __init__(self, spec: str) -> None:
"""
Initialize from hash specification string.
Parameters:
- spec: Hash specification in format 'algorithm=value' (e.g., 'sha256=abc123...')
"""
def __repr__(self) -> str:
"""
String representation of the file hash.
Returns:
str: Representation showing hash mode and value
"""import importlib_metadata
# Find files with hashes
files = importlib_metadata.files('requests')
if files:
hashed_files = [f for f in files if f.hash]
print(f"Found {len(hashed_files)} files with hash information")
for file_path in hashed_files[:3]: # Show first 3
hash_info = file_path.hash
print(f"File: {file_path}")
print(f" Hash algorithm: {hash_info.mode}")
print(f" Hash value: {hash_info.value[:16]}...") # Show first 16 charsProtocol interface for path-like objects used throughout the library:
class SimplePath(Protocol):
"""
A minimal subset of pathlib.Path required by Distribution.
Defines the interface that path objects must implement to work
with the importlib_metadata system.
"""
def joinpath(self, other: str | os.PathLike[str]) -> SimplePath:
"""
Join this path with another path component.
Parameters:
- other: Path component to join
Returns:
SimplePath: New path with component joined
"""
def __truediv__(self, other: str | os.PathLike[str]) -> SimplePath:
"""
Path division operator (/).
Parameters:
- other: Path component to join
Returns:
SimplePath: New path with component joined
"""
@property
def parent(self) -> SimplePath:
"""
Return the parent directory of this path.
Returns:
SimplePath: Parent directory path
"""
def read_text(self, encoding=None) -> str:
"""
Read the file as text.
Parameters:
- encoding: Text encoding (optional)
Returns:
str: File contents as text
"""
def read_bytes(self) -> bytes:
"""
Read the file as binary data.
Returns:
bytes: File contents as bytes
"""
def exists(self) -> bool:
"""
Check if the path exists.
Returns:
bool: True if path exists
"""Working with package file collections:
import importlib_metadata
# Get all files for a package
files = importlib_metadata.files('requests')
if files:
print(f"Total files: {len(files)}")
# Filter by file type
py_files = [f for f in files if f.suffix == '.py']
print(f"Python files: {len(py_files)}")
# Filter by directory
lib_files = [f for f in files if 'requests' in f.parts]
print(f"Files in requests directory: {len(lib_files)}")
# Find specific files
init_files = [f for f in files if f.name == '__init__.py']
print(f"__init__.py files: {len(init_files)}")
# Files with specific extensions
data_files = [f for f in files if f.suffix in ['.txt', '.rst', '.md']]
print(f"Documentation files: {len(data_files)}")
# Large files
large_files = [f for f in files if f.size > 10000] # > 10KB
print(f"Large files (>10KB): {len(large_files)}")Reading and processing package files:
import importlib_metadata
# Get package files
files = importlib_metadata.files('requests')
if files:
# Read text files
for file_path in files:
if file_path.name == 'MANIFEST.in':
try:
content = file_path.read_text()
print(f"MANIFEST.in content:\n{content}")
break
except Exception as e:
print(f"Could not read MANIFEST.in: {e}")
# Read binary files
for file_path in files:
if file_path.suffix == '.whl': # If any wheel files
try:
data = file_path.read_binary()
print(f"Binary file {file_path.name}: {len(data)} bytes")
break
except Exception as e:
print(f"Could not read binary file: {e}")
# Check file existence
for file_path in files[:5]:
actual_path = file_path.locate()
exists = actual_path.exists()
print(f"File {file_path.name} exists: {exists}")Working with actual file system paths:
import importlib_metadata
from pathlib import Path
# Get distribution and locate files
dist = importlib_metadata.distribution('requests')
files = dist.files
if files:
# Get actual file system paths
for file_path in files[:3]:
actual_path = file_path.locate()
# Convert to pathlib.Path if needed
if hasattr(actual_path, 'resolve'):
resolved = actual_path.resolve()
print(f"File: {file_path}")
print(f" Actual path: {resolved}")
print(f" Exists: {resolved.exists()}")File operations can raise various exceptions:
import importlib_metadata
files = importlib_metadata.files('requests')
if files:
file_path = files[0]
# Handle file reading errors
try:
content = file_path.read_text()
except UnicodeDecodeError:
print("File is not valid text")
content = file_path.read_binary()
except FileNotFoundError:
print("File not found on filesystem")
except PermissionError:
print("Permission denied")
# Handle path location errors
try:
actual_path = file_path.locate()
except NotImplementedError:
print("Distribution doesn't support file location")Install with Tessl CLI
npx tessl i tessl/pypi-importlib-metadata@8.7.2