0
# Validation System
1
2
Comprehensive validation system with configurable checks for common wheel packaging issues. Supports built-in checks (W001-W202) covering bytecode files, duplicates, module placement, library structure, and package completeness.
3
4
## Capabilities
5
6
### Wheel Validation
7
8
Main validation orchestrator that runs selected checks against wheel contents and reports failures with detailed diagnostic information.
9
10
```python { .api }
11
class WheelChecker:
12
"""A class for performing various checks on a WheelContents instance"""
13
14
def __init__(self, selected: set[Check] | None = None,
15
toplevel: list[str] | None = None,
16
pkgtree: Directory | None = None):
17
"""
18
Initialize wheel checker.
19
20
Parameters:
21
- selected: Set of checks to run, or None for all checks
22
- toplevel: Expected toplevel library entries for W2 checks
23
- pkgtree: Expected package structure for W1 checks
24
"""
25
26
def configure_options(self, configpath=None, select: set[Check] | None = None,
27
ignore: set[Check] | None = None,
28
toplevel: list[str] | None = None,
29
package: tuple[str, ...] = (),
30
src_dir: tuple[str, ...] = (),
31
package_omit: list[str] | None = None) -> None:
32
"""
33
Configure checker options from various sources.
34
35
Parameters:
36
- configpath: Path to configuration file, or NO_CONFIG to disable
37
- select: Specific checks to enable
38
- ignore: Specific checks to disable
39
- toplevel: List of expected toplevel library entries
40
- package: Tuple of package paths to expect in wheel
41
- src_dir: Tuple of source directories to expect contents of
42
- package_omit: Patterns to omit when traversing package/src_dir
43
44
Raises:
45
- UserInputError: If configuration is invalid
46
"""
47
48
def check_contents(self, contents: WheelContents) -> list[FailedCheck]:
49
"""
50
Run all selected checks on wheel contents.
51
52
Parameters:
53
- contents: WheelContents instance to check
54
55
Returns:
56
List of FailedCheck instances for any failures
57
"""
58
```
59
60
### Check Types and Failures
61
62
Enumeration of all available validation checks and representation of check failures with diagnostic information.
63
64
```python { .api }
65
class Check(Enum):
66
"""Enumeration of validation checks and their error messages"""
67
68
# Basic content checks
69
W001 = "Wheel contains .pyc/.pyo files"
70
W002 = "Wheel contains duplicate files"
71
W003 = "Wheel contains non-module at library toplevel"
72
W004 = "Module is not located at importable path"
73
W005 = "Wheel contains common toplevel name in library"
74
W006 = "__init__.py at top level of library"
75
W007 = "Wheel library is empty"
76
W008 = "Wheel is empty"
77
W009 = "Wheel contains multiple toplevel library entries"
78
W010 = "Toplevel library directory contains no Python modules"
79
80
# Package structure checks
81
W101 = "Wheel library is missing files in package tree"
82
W102 = "Wheel library contains files not in package tree"
83
84
# Toplevel specification checks
85
W201 = "Wheel library is missing specified toplevel entry"
86
W202 = "Wheel library has undeclared toplevel entry"
87
88
class FailedCheck:
89
"""A check that has failed"""
90
91
def __init__(self, check: Check, args: list[str] | None = None):
92
"""
93
Initialize failed check.
94
95
Parameters:
96
- check: The check that failed
97
- args: Relevant filepaths or other diagnostic information
98
"""
99
100
def show(self, filename: str | None = None) -> str:
101
"""
102
Format failure message for display.
103
104
Parameters:
105
- filename: Name of wheel being checked (optional)
106
107
Returns:
108
Formatted error message string
109
"""
110
```
111
112
### Check Parsing and Selection
113
114
Utilities for parsing check specifications from command-line and configuration files, supporting check names, prefixes, and ranges.
115
116
```python { .api }
117
def parse_checks_string(s: str) -> set[Check]:
118
"""
119
Parse comma-separated check names and prefixes.
120
121
Parameters:
122
- s: Comma-separated string of check names/prefixes
123
124
Returns:
125
Set of Check instances
126
127
Raises:
128
- UserInputError: If any check name/prefix is invalid
129
"""
130
131
def parse_check_prefixes(prefixes: list[str]) -> set[Check]:
132
"""
133
Parse list of check names and prefixes.
134
135
Parameters:
136
- prefixes: List of check names and prefixes
137
138
Returns:
139
Set of Check instances
140
141
Raises:
142
- UserInputError: If any check name/prefix is invalid
143
"""
144
145
def parse_check_prefix(s: str) -> set[Check]:
146
"""
147
Parse single check name or prefix.
148
149
Parameters:
150
- s: Check name or prefix (e.g., "W001", "W1", "W")
151
152
Returns:
153
Set of matching Check instances
154
155
Raises:
156
- UserInputError: If check name/prefix is invalid
157
"""
158
```
159
160
### Usage Examples
161
162
```python
163
from check_wheel_contents import WheelChecker, WheelContents
164
from check_wheel_contents.checks import Check, parse_checks_string
165
from check_wheel_contents.errors import UserInputError
166
167
# Create checker with default settings (all checks enabled)
168
checker = WheelChecker()
169
170
# Create checker with specific checks
171
selected_checks = {Check.W001, Check.W002, Check.W003}
172
checker = WheelChecker(selected=selected_checks)
173
174
# Configure from command-line style options
175
checker = WheelChecker()
176
try:
177
checker.configure_options(
178
select=parse_checks_string("W1,W2"), # Enable W1xx and W2xx checks
179
ignore=parse_checks_string("W005"), # Disable W005
180
toplevel=["mypackage", "mypackage.ext"]
181
)
182
except UserInputError as e:
183
print(f"Configuration error: {e}")
184
185
# Run checks on wheel
186
contents = WheelContents.from_wheel("dist/mypackage-1.0.0-py3-none-any.whl")
187
failures = checker.check_contents(contents)
188
189
# Process results
190
if failures:
191
print("Validation failures:")
192
for failure in failures:
193
print(f" {failure.show()}")
194
if failure.args:
195
for arg in failure.args:
196
print(f" - {arg}")
197
else:
198
print("All checks passed!")
199
200
# Check for specific issues
201
bytecode_failures = [f for f in failures if f.check == Check.W001]
202
if bytecode_failures:
203
print("Bytecode files found:")
204
for f in bytecode_failures:
205
for path in f.args:
206
print(f" {path}")
207
208
# Parse check specifications
209
try:
210
w1_checks = parse_checks_string("W1") # All W1xx checks
211
specific = parse_checks_string("W001,W005") # Specific checks
212
combined = parse_checks_string("W1,W201") # Mix of prefix and specific
213
except UserInputError as e:
214
print(f"Invalid check specification: {e}")
215
```