0
# Check Wheel Contents
1
2
A Python library and command-line tool for validating the contents of Python wheel distribution packages. It performs comprehensive checks to detect common packaging errors and ensures wheels contain appropriate files, helping developers avoid publishing wheels with issues like compiled bytecode files, duplicate files, modules in wrong locations, or missing package components.
3
4
## Package Information
5
6
- **Package Name**: check-wheel-contents
7
- **Language**: Python
8
- **Installation**: `pip install check-wheel-contents`
9
- **Python Requirements**: >=3.10
10
11
## Core Imports
12
13
```python
14
import check_wheel_contents
15
from check_wheel_contents import WheelChecker, WheelContents, Configuration
16
from check_wheel_contents.checks import Check, FailedCheck
17
from check_wheel_contents.errors import UserInputError, WheelValidationError
18
```
19
20
## Basic Usage
21
22
### Command Line Interface
23
24
```bash
25
# Check a single wheel
26
check-wheel-contents path/to/your-package-1.0.0-py3-none-any.whl
27
28
# Check all wheels in a directory
29
check-wheel-contents ./dist/
30
31
# Check with custom configuration
32
check-wheel-contents --config pyproject.toml path/to/wheel.whl
33
34
# Ignore specific checks
35
check-wheel-contents --ignore W001,W002 path/to/wheel.whl
36
37
# Select only specific checks
38
check-wheel-contents --select W1 path/to/wheel.whl
39
```
40
41
### Programmatic Usage
42
43
```python
44
from pathlib import Path
45
from check_wheel_contents import WheelChecker, WheelContents
46
from check_wheel_contents.checks import Check
47
48
# Create a checker instance
49
checker = WheelChecker()
50
51
# Load and analyze a wheel
52
wheel_path = Path("dist/my-package-1.0.0-py3-none-any.whl")
53
contents = WheelContents.from_wheel(wheel_path)
54
55
# Run all checks
56
failures = checker.check_contents(contents)
57
58
# Process results
59
if failures:
60
for failure in failures:
61
print(failure.show(str(wheel_path)))
62
else:
63
print(f"{wheel_path}: OK")
64
```
65
66
## Architecture
67
68
The package follows a modular architecture with clear separation of concerns:
69
70
- **WheelChecker**: Main orchestrator that runs validation checks on wheel contents
71
- **WheelContents**: Parses and represents the internal structure of wheel files
72
- **Configuration**: Manages settings from files and command-line options
73
- **Check/FailedCheck**: Enumeration and representation of validation rules and failures
74
- **File/Directory**: Hierarchical representation of wheel file trees
75
- **Utilities**: Helper functions for path validation, file analysis, and format parsing
76
77
## Capabilities
78
79
### Wheel Content Analysis
80
81
Core functionality for parsing wheel files and extracting their internal structure. Provides detailed representation of files, directories, metadata, and distribution information.
82
83
```python { .api }
84
class WheelContents:
85
dist_info_dir: str
86
data_dir: str
87
root_is_purelib: bool
88
by_signature: dict[tuple[int | None, str | None], list[File]]
89
filetree: Directory
90
91
@classmethod
92
def from_wheel(cls, wheel_path: Path) -> 'WheelContents': ...
93
94
@property
95
def purelib_tree(self) -> Directory: ...
96
97
@property
98
def platlib_tree(self) -> Directory: ...
99
```
100
101
[Wheel Analysis](./wheel-analysis.md)
102
103
### Validation Checking
104
105
Comprehensive validation system with configurable checks for common wheel packaging issues. Supports built-in checks (W001-W202) and custom validation rules.
106
107
```python { .api }
108
class WheelChecker:
109
selected: set[Check]
110
toplevel: list[str] | None
111
pkgtree: Directory | None
112
113
def configure_options(self, configpath=None, select: set[Check] | None = None,
114
ignore: set[Check] | None = None,
115
toplevel: list[str] | None = None,
116
package: tuple[str, ...] = (),
117
src_dir: tuple[str, ...] = (),
118
package_omit: list[str] | None = None) -> None: ...
119
120
def check_contents(self, contents: WheelContents) -> list[FailedCheck]: ...
121
```
122
123
[Validation System](./validation.md)
124
125
### Configuration Management
126
127
Flexible configuration system supporting multiple file formats (TOML, INI) and command-line overrides. Handles check selection, package expectations, and directory traversal patterns.
128
129
```python { .api }
130
class Configuration:
131
select: set[Check] | None
132
ignore: set[Check] | None
133
toplevel: list[str] | None
134
package_paths: list[Path] | None
135
src_dirs: list[Path] | None
136
package_omit: list[str] | None
137
138
@classmethod
139
def from_config_file(cls, path: str | None = None) -> 'Configuration': ...
140
```
141
142
[Configuration](./configuration.md)
143
144
## Types
145
146
```python { .api }
147
class Check(Enum):
148
W001 = "Wheel contains .pyc/.pyo files"
149
W002 = "Wheel contains duplicate files"
150
W003 = "Wheel contains non-module at library toplevel"
151
W004 = "Module is not located at importable path"
152
W005 = "Wheel contains common toplevel name in library"
153
W006 = "__init__.py at top level of library"
154
W007 = "Wheel library is empty"
155
W008 = "Wheel is empty"
156
W009 = "Wheel contains multiple toplevel library entries"
157
W010 = "Toplevel library directory contains no Python modules"
158
W101 = "Wheel library is missing files in package tree"
159
W102 = "Wheel library contains files not in package tree"
160
W201 = "Wheel library is missing specified toplevel entry"
161
W202 = "Wheel library has undeclared toplevel entry"
162
163
class FailedCheck:
164
check: Check
165
args: list[str]
166
167
def show(self, filename: str | None = None) -> str: ...
168
169
class File:
170
parts: tuple[str, ...]
171
size: int | None
172
hashsum: str | None
173
174
@classmethod
175
def from_record_row(cls, row: list[str]) -> 'File': ...
176
177
@property
178
def path(self) -> str: ...
179
@property
180
def signature(self) -> tuple[int | None, str | None]: ...
181
182
class Directory:
183
path: str | None
184
entries: dict[str, File | 'Directory']
185
186
@classmethod
187
def from_record_rows(cls, rows: list[list[str]]) -> 'Directory': ...
188
189
def iterdir(self) -> Iterator[File | 'Directory']: ...
190
def lookup(self, path: str) -> File | 'Directory' | None: ...
191
192
class UserInputError(ValueError):
193
"""Exception for invalid user input values"""
194
195
class WheelValidationError(Exception):
196
"""Exception for invalid or malformed wheels"""
197
```