python-skills 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_skills/__init__.py +10 -0
- python_skills/__main__.py +6 -0
- python_skills/adapters/__init__.py +48 -0
- python_skills/adapters/agent_skills.py +415 -0
- python_skills/adapters/aider_adapter.py +226 -0
- python_skills/adapters/base.py +153 -0
- python_skills/adapters/claude.py +474 -0
- python_skills/adapters/cline.py +332 -0
- python_skills/adapters/codex.py +24 -0
- python_skills/adapters/continue_adapter.py +198 -0
- python_skills/adapters/cursor.py +327 -0
- python_skills/adapters/gemini.py +26 -0
- python_skills/adapters/goose.py +26 -0
- python_skills/adapters/junie.py +25 -0
- python_skills/adapters/kiro.py +382 -0
- python_skills/adapters/opencode.py +27 -0
- python_skills/adapters/roo.py +25 -0
- python_skills/adapters/universal.py +203 -0
- python_skills/adapters/vscode.py +27 -0
- python_skills/adapters/windsurf.py +26 -0
- python_skills/adapters/zed.py +27 -0
- python_skills/cli.py +326 -0
- python_skills/config.py +160 -0
- python_skills/detector.py +152 -0
- python_skills/installer.py +163 -0
- python_skills/markers.py +115 -0
- python_skills/skills/__init__.py +14 -0
- python_skills/skills/loader.py +171 -0
- python_skills/skills/metadata.py +152 -0
- python_skills/skills/registry.py +101 -0
- python_skills/state.py +204 -0
- python_skills-1.0.0.dist-info/METADATA +99 -0
- python_skills-1.0.0.dist-info/RECORD +105 -0
- python_skills-1.0.0.dist-info/WHEEL +4 -0
- python_skills-1.0.0.dist-info/entry_points.txt +2 -0
- python_skills-1.0.0.dist-info/licenses/LICENSE +21 -0
- skills/advanced_python.md +239 -0
- skills/anti_patterns/index.md +406 -0
- skills/comprehensions.md +167 -0
- skills/control_flow.md +175 -0
- skills/data_structures.md +243 -0
- skills/debugging/common_bugs.md +222 -0
- skills/debugging/inspection_techniques.md +249 -0
- skills/debugging/root_cause.md +203 -0
- skills/engineering/application_logging.md +195 -0
- skills/engineering/cli_apps.md +207 -0
- skills/engineering/configuration.md +218 -0
- skills/engineering/database.md +240 -0
- skills/engineering/dependency_management.md +205 -0
- skills/engineering/http_clients.md +267 -0
- skills/engineering/modules_packages.md +211 -0
- skills/engineering/packaging.md +197 -0
- skills/engineering/project_structure.md +155 -0
- skills/engineering/pyproject_toml.md +302 -0
- skills/engineering/virtual_environments.md +206 -0
- skills/functions.md +244 -0
- skills/generation/async_concurrency.md +291 -0
- skills/generation/error_handling.md +276 -0
- skills/generation/protocols_generics.md +243 -0
- skills/generation/type_hints.md +290 -0
- skills/generation/validation_pipeline.md +274 -0
- skills/generation/workflow.md +190 -0
- skills/oop.md +228 -0
- skills/quality/abstractions.md +154 -0
- skills/quality/comments.md +177 -0
- skills/quality/documentation.md +176 -0
- skills/quality/duplication.md +137 -0
- skills/quality/maintainability.md +142 -0
- skills/quality/naming.md +171 -0
- skills/quality/quality_functions.md +245 -0
- skills/quality/readability.md +239 -0
- skills/quality/type_annotations.md +192 -0
- skills/refactoring/behavior_preservation.md +157 -0
- skills/refactoring/incremental.md +187 -0
- skills/refactoring/interface_stability.md +199 -0
- skills/refactoring/safe_refactoring.md +206 -0
- skills/security/auth_boundaries.md +200 -0
- skills/security/command_injection.md +207 -0
- skills/security/dependency_risks.md +282 -0
- skills/security/file_handling.md +156 -0
- skills/security/input_validation.md +190 -0
- skills/security/path_traversal.md +172 -0
- skills/security/secrets.md +171 -0
- skills/security/sql_injection.md +188 -0
- skills/security/unsafe_deserialization.md +164 -0
- skills/stdlib/argparse.md +178 -0
- skills/stdlib/collections.md +212 -0
- skills/stdlib/datetime.md +187 -0
- skills/stdlib/functools.md +238 -0
- skills/stdlib/itertools.md +183 -0
- skills/stdlib/json.md +162 -0
- skills/stdlib/logging.md +185 -0
- skills/stdlib/os_sys.md +184 -0
- skills/stdlib/pathlib.md +218 -0
- skills/stdlib/re.md +171 -0
- skills/stdlib/statistics.md +112 -0
- skills/stdlib/subprocess.md +211 -0
- skills/testing/async_tests.md +249 -0
- skills/testing/coverage.md +168 -0
- skills/testing/edge_cases.md +197 -0
- skills/testing/fixtures_mocks.md +203 -0
- skills/testing/organization.md +205 -0
- skills/testing/parameterized.md +174 -0
- skills/testing/regression_tests.md +165 -0
- skills/variables_types.md +107 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# Generation: Type Hints
|
|
2
|
+
|
|
3
|
+
**Purpose**: Modern Python typing guidance for code generation.
|
|
4
|
+
|
|
5
|
+
**When to use**: All code generation. Type hints improve correctness and maintainability.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Rules
|
|
10
|
+
|
|
11
|
+
### Basic Annotations
|
|
12
|
+
```python
|
|
13
|
+
# Variables
|
|
14
|
+
count: int = 0
|
|
15
|
+
name: str = "default"
|
|
16
|
+
items: list[str] = []
|
|
17
|
+
mapping: dict[str, int] = {}
|
|
18
|
+
|
|
19
|
+
# Functions
|
|
20
|
+
def func(arg: int, optional: str = "default") -> bool:
|
|
21
|
+
...
|
|
22
|
+
|
|
23
|
+
# Classes
|
|
24
|
+
class MyClass:
|
|
25
|
+
attr: int
|
|
26
|
+
def method(self, x: float) -> str: ...
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Built-in Generics (Python 3.9+)
|
|
30
|
+
```python
|
|
31
|
+
# Preferred (no typing import needed)
|
|
32
|
+
list[str]
|
|
33
|
+
dict[str, int]
|
|
34
|
+
set[int]
|
|
35
|
+
tuple[int, str, bool]
|
|
36
|
+
tuple[int, ...] # Variable-length tuple
|
|
37
|
+
collections.abc.Iterable[int]
|
|
38
|
+
collections.abc.Sequence[str]
|
|
39
|
+
collections.abc.Mapping[str, int]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Union Types (Python 3.10+)
|
|
43
|
+
```python
|
|
44
|
+
# Preferred
|
|
45
|
+
int | str
|
|
46
|
+
list[int | str]
|
|
47
|
+
dict[str, int | None]
|
|
48
|
+
|
|
49
|
+
# Legacy (still works)
|
|
50
|
+
from typing import Union
|
|
51
|
+
Union[int, str]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Optional
|
|
55
|
+
```python
|
|
56
|
+
# Python 3.10+
|
|
57
|
+
str | None
|
|
58
|
+
|
|
59
|
+
# Legacy
|
|
60
|
+
from typing import Optional
|
|
61
|
+
Optional[str]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Type Aliases (Python 3.12+)
|
|
65
|
+
```python
|
|
66
|
+
type JSONValue = str | int | float | bool | None | list["JSONValue"] | dict[str, "JSONValue"]
|
|
67
|
+
type UserID = int
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### TypeVar and Generics
|
|
71
|
+
```python
|
|
72
|
+
from typing import TypeVar, Generic
|
|
73
|
+
|
|
74
|
+
T = TypeVar("T")
|
|
75
|
+
K = TypeVar("K")
|
|
76
|
+
V = TypeVar("V")
|
|
77
|
+
|
|
78
|
+
class Container(Generic[T]):
|
|
79
|
+
def __init__(self, value: T) -> None:
|
|
80
|
+
self.value = value
|
|
81
|
+
|
|
82
|
+
def get(self) -> T:
|
|
83
|
+
return self.value
|
|
84
|
+
|
|
85
|
+
# Usage
|
|
86
|
+
int_container: Container[int] = Container(42)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Protocols (Structural Typing)
|
|
90
|
+
```python
|
|
91
|
+
from typing import Protocol
|
|
92
|
+
|
|
93
|
+
class Drawable(Protocol):
|
|
94
|
+
def draw(self) -> None: ...
|
|
95
|
+
|
|
96
|
+
class Circle:
|
|
97
|
+
def draw(self) -> None: # Implicitly implements Drawable
|
|
98
|
+
...
|
|
99
|
+
|
|
100
|
+
def render(d: Drawable) -> None:
|
|
101
|
+
d.draw()
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Callable Types
|
|
105
|
+
```python
|
|
106
|
+
from typing import Callable
|
|
107
|
+
|
|
108
|
+
# Function taking (int, str) returning bool
|
|
109
|
+
callback: Callable[[int, str], bool]
|
|
110
|
+
|
|
111
|
+
# More flexible
|
|
112
|
+
from collections.abc import Callable
|
|
113
|
+
handler: Callable[..., Any]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### TypedDict (Structured Dicts)
|
|
117
|
+
```python
|
|
118
|
+
from typing import TypedDict, NotRequired
|
|
119
|
+
|
|
120
|
+
class UserDict(TypedDict):
|
|
121
|
+
id: int
|
|
122
|
+
name: str
|
|
123
|
+
email: NotRequired[str] # Optional key (3.11+)
|
|
124
|
+
# or: email: str | None # Required key, nullable value
|
|
125
|
+
|
|
126
|
+
def process_user(user: UserDict) -> None:
|
|
127
|
+
print(user["name"])
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Dataclasses with Types
|
|
131
|
+
```python
|
|
132
|
+
from dataclasses import dataclass
|
|
133
|
+
from typing import Optional
|
|
134
|
+
|
|
135
|
+
@dataclass
|
|
136
|
+
class User:
|
|
137
|
+
id: int
|
|
138
|
+
name: str
|
|
139
|
+
email: Optional[str] = None
|
|
140
|
+
tags: list[str] = field(default_factory=list)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Overloads
|
|
144
|
+
```python
|
|
145
|
+
from typing import overload
|
|
146
|
+
|
|
147
|
+
@overload
|
|
148
|
+
def func(x: int) -> int: ...
|
|
149
|
+
@overload
|
|
150
|
+
def func(x: str) -> str: ...
|
|
151
|
+
def func(x: int | str) -> int | str:
|
|
152
|
+
return x
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Final and Literal
|
|
156
|
+
```python
|
|
157
|
+
from typing import Final, Literal
|
|
158
|
+
|
|
159
|
+
MAX_SIZE: Final = 100
|
|
160
|
+
Mode = Literal["fast", "slow", "auto"]
|
|
161
|
+
mode: Mode = "fast"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Self Type (Python 3.11+)
|
|
165
|
+
```python
|
|
166
|
+
from typing import Self
|
|
167
|
+
|
|
168
|
+
class Builder:
|
|
169
|
+
def set_name(self, name: str) -> Self:
|
|
170
|
+
self.name = name
|
|
171
|
+
return self
|
|
172
|
+
|
|
173
|
+
def build(self) -> Product:
|
|
174
|
+
return Product(self.name)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Type Narrowing
|
|
178
|
+
```python
|
|
179
|
+
def process(value: int | str) -> str:
|
|
180
|
+
if isinstance(value, int):
|
|
181
|
+
return str(value) # value is int here
|
|
182
|
+
return value # value is str here
|
|
183
|
+
|
|
184
|
+
# With user-defined guards
|
|
185
|
+
from typing import TypeGuard
|
|
186
|
+
|
|
187
|
+
def is_int_list(value: list[int] | list[str]) -> TypeGuard[list[int]]:
|
|
188
|
+
return all(isinstance(x, int) for x in value)
|
|
189
|
+
|
|
190
|
+
if is_int_list(items):
|
|
191
|
+
# items is list[int] here
|
|
192
|
+
...
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Decision Rules
|
|
198
|
+
|
|
199
|
+
| Situation | Choice |
|
|
200
|
+
|-----------|--------|
|
|
201
|
+
| Simple function | Full annotations |
|
|
202
|
+
| Internal helper | Light annotations or inference |
|
|
203
|
+
| Public API | Full annotations + docstring |
|
|
204
|
+
| Generic container | `Generic[T]` |
|
|
205
|
+
| Interface | `Protocol` |
|
|
206
|
+
| Dict with fixed keys | `TypedDict` |
|
|
207
|
+
| Union of few types | `A | B` |
|
|
208
|
+
| Many union types | `Union[A, B, C, ...]` |
|
|
209
|
+
| Callable | `Callable[[Args], Return]` |
|
|
210
|
+
| Constant | `Final` |
|
|
211
|
+
| Limited string values | `Literal` |
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Useful vs Noise
|
|
216
|
+
|
|
217
|
+
### Useful
|
|
218
|
+
- Function signatures (public API)
|
|
219
|
+
- Complex data structures
|
|
220
|
+
- Generic classes
|
|
221
|
+
- Protocol interfaces
|
|
222
|
+
- Return types of non-trivial functions
|
|
223
|
+
|
|
224
|
+
### Noise
|
|
225
|
+
- Obvious local variables: `x: int = 5`
|
|
226
|
+
- Loop variables: `for i: int in range(10):`
|
|
227
|
+
- Trivial helpers with clear types
|
|
228
|
+
- Over-annotating private implementation
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Project Compatibility
|
|
233
|
+
|
|
234
|
+
Respect project's Python version and config:
|
|
235
|
+
- Check `pyproject.toml` for `[tool.mypy]` or `[tool.pyright]`
|
|
236
|
+
- Python 3.9+: built-in generics
|
|
237
|
+
- Python 3.10+: `|` union, `TypeGuard`
|
|
238
|
+
- Python 3.11+: `Self`, `NotRequired`, `TypedDict` improvements
|
|
239
|
+
- Python 3.12+: `type` alias, `**kwargs` typing
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Preferred Patterns
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
# Public API — full types
|
|
247
|
+
def fetch_users(
|
|
248
|
+
client: APIClient,
|
|
249
|
+
filters: UserFilters | None = None,
|
|
250
|
+
limit: int = 100,
|
|
251
|
+
) -> list[User]:
|
|
252
|
+
...
|
|
253
|
+
|
|
254
|
+
# Internal — inference OK
|
|
255
|
+
def _parse_line(line: str) -> ParsedLine:
|
|
256
|
+
parts = line.split(",")
|
|
257
|
+
return ParsedLine(int(parts[0]), parts[1])
|
|
258
|
+
|
|
259
|
+
# Generic utility
|
|
260
|
+
def first_item[T](items: Sequence[T]) -> T | None:
|
|
261
|
+
return items[0] if items else None
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Avoid
|
|
267
|
+
|
|
268
|
+
- `Any` without justification (disable checking)
|
|
269
|
+
- `object` as "I don't know" (use `Any` or proper type)
|
|
270
|
+
- Complex nested types without aliases
|
|
271
|
+
- Type hints that lie (incorrect types)
|
|
272
|
+
- Ignoring type checker errors without `# type: ignore` comment with reason
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Validation Considerations
|
|
277
|
+
|
|
278
|
+
- Run type checker (`mypy`, `pyright`) on project
|
|
279
|
+
- `--strict` mode for new projects
|
|
280
|
+
- `# type: ignore[code]` with specific error code
|
|
281
|
+
- `typing.TYPE_CHECKING` for imports only needed for types
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Related Skills
|
|
286
|
+
|
|
287
|
+
- `generation/protocols_generics.md`
|
|
288
|
+
- `generation/workflow.md`
|
|
289
|
+
- `quality/type_annotations.md`
|
|
290
|
+
- `engineering/pyproject_toml.md` (tool config)
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Generation: Validation Pipeline
|
|
2
|
+
|
|
3
|
+
**Purpose**: Concrete validation process for generated code.
|
|
4
|
+
|
|
5
|
+
**When to use**: After every code generation or modification.
|
|
6
|
+
---
|
|
7
|
+
---
|
|
8
|
+
name: generation_validation_pipeline
|
|
9
|
+
purpose: Concrete validation process for generated code
|
|
10
|
+
category: generation
|
|
11
|
+
triggers:
|
|
12
|
+
- validation
|
|
13
|
+
- pipeline
|
|
14
|
+
- verification
|
|
15
|
+
- testing
|
|
16
|
+
- linting
|
|
17
|
+
- type checking
|
|
18
|
+
dependencies:
|
|
19
|
+
- generation/workflow.md
|
|
20
|
+
- generation/type_hints.md
|
|
21
|
+
- generation/error_handling.md
|
|
22
|
+
- testing/organization.md
|
|
23
|
+
- engineering/pyproject_toml.md
|
|
24
|
+
- security/dependency_risks.md
|
|
25
|
+
priority: primary
|
|
26
|
+
estimated_tokens: 2000
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Validation Steps (In Order)
|
|
30
|
+
|
|
31
|
+
### 1. Syntax Check
|
|
32
|
+
```bash
|
|
33
|
+
python -m py_compile file.py
|
|
34
|
+
# or
|
|
35
|
+
python -m py_compile module/
|
|
36
|
+
```
|
|
37
|
+
- Catches syntax errors, indentation errors
|
|
38
|
+
- Fast, runs on single file or directory
|
|
39
|
+
|
|
40
|
+
### 2. Type Checking
|
|
41
|
+
```bash
|
|
42
|
+
# Detect tool from pyproject.toml
|
|
43
|
+
mypy file.py
|
|
44
|
+
# or
|
|
45
|
+
pyright file.py
|
|
46
|
+
# or
|
|
47
|
+
pytype file.py
|
|
48
|
+
```
|
|
49
|
+
- Catches type mismatches, missing annotations
|
|
50
|
+
- Use project's config (`[tool.mypy]`, `pyrightconfig.json`)
|
|
51
|
+
- `--strict` for new code
|
|
52
|
+
|
|
53
|
+
### 3. Linting
|
|
54
|
+
```bash
|
|
55
|
+
ruff check file.py
|
|
56
|
+
# or
|
|
57
|
+
flake8 file.py
|
|
58
|
+
# or
|
|
59
|
+
pylint file.py
|
|
60
|
+
```
|
|
61
|
+
- Catches style issues, potential bugs, complexity
|
|
62
|
+
- Use project's config (`ruff.toml`, `.flake8`, `setup.cfg`)
|
|
63
|
+
|
|
64
|
+
### 4. Formatting Check
|
|
65
|
+
```bash
|
|
66
|
+
ruff format --check file.py
|
|
67
|
+
# or
|
|
68
|
+
black --check file.py
|
|
69
|
+
```
|
|
70
|
+
- Ensures consistent formatting
|
|
71
|
+
- Run formatter if check fails: `ruff format file.py`
|
|
72
|
+
|
|
73
|
+
### 5. Tests
|
|
74
|
+
```bash
|
|
75
|
+
# Detect test framework
|
|
76
|
+
pytest path/to/tests -v
|
|
77
|
+
# or
|
|
78
|
+
python -m pytest
|
|
79
|
+
# or
|
|
80
|
+
tox
|
|
81
|
+
```
|
|
82
|
+
- Run relevant tests (changed files + related)
|
|
83
|
+
- Full suite for significant changes
|
|
84
|
+
|
|
85
|
+
### 6. Relevant Execution
|
|
86
|
+
```bash
|
|
87
|
+
# Run the actual code if possible
|
|
88
|
+
python -m module arg1 arg2
|
|
89
|
+
# or
|
|
90
|
+
python script.py
|
|
91
|
+
```
|
|
92
|
+
- Smoke test the functionality
|
|
93
|
+
- Verify integration works
|
|
94
|
+
|
|
95
|
+
### 7. Security Scan (Optional)
|
|
96
|
+
```bash
|
|
97
|
+
bandit -r file.py
|
|
98
|
+
# or
|
|
99
|
+
safety check
|
|
100
|
+
```
|
|
101
|
+
- Security linting
|
|
102
|
+
- Dependency vulnerability check
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Project Tool Detection
|
|
107
|
+
|
|
108
|
+
Check for config files in project root:
|
|
109
|
+
```bash
|
|
110
|
+
ls pyproject.toml setup.cfg tox.ini ruff.toml .pre-commit-config.yaml pyrightconfig.json
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
| File | Tools |
|
|
114
|
+
|------|-------|
|
|
115
|
+
| `pyproject.toml` | `[tool.mypy]`, `[tool.ruff]`, `[tool.black]`, `[tool.pytest]`, `[tool.bandit]` |
|
|
116
|
+
| `ruff.toml` | Ruff config |
|
|
117
|
+
| `pyrightconfig.json` | Pyright config |
|
|
118
|
+
| `setup.cfg` | `[flake8]`, `[mypy]`, `[tool:pytest]` |
|
|
119
|
+
| `tox.ini` | Test environments |
|
|
120
|
+
| `.pre-commit-config.yaml` | Pre-commit hooks |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Never Claim Without Evidence
|
|
125
|
+
|
|
126
|
+
| Claim | Required Evidence |
|
|
127
|
+
|-------|-------------------|
|
|
128
|
+
| "tested" | Test output showing pass |
|
|
129
|
+
| "verified" | Validation pipeline output |
|
|
130
|
+
| "linted" | Linter output (clean) |
|
|
131
|
+
| "type-safe" | Type checker output (clean) |
|
|
132
|
+
| "production-ready" | All above + security scan |
|
|
133
|
+
| "fixed" | Reproduction + fix + regression test |
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Validation Script Template
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
#!/usr/bin/env python3
|
|
141
|
+
"""Validation pipeline for generated code."""
|
|
142
|
+
import subprocess
|
|
143
|
+
import sys
|
|
144
|
+
from pathlib import Path
|
|
145
|
+
|
|
146
|
+
def run(cmd: list[str], cwd: Path | None = None) -> subprocess.CompletedProcess:
|
|
147
|
+
return subprocess.run(cmd, cwd=cwd, capture_output=True, text=True)
|
|
148
|
+
|
|
149
|
+
def check_syntax(path: Path) -> bool:
|
|
150
|
+
result = run([sys.executable, "-m", "py_compile", str(path)])
|
|
151
|
+
if result.returncode != 0:
|
|
152
|
+
print(f"Syntax error: {result.stderr}")
|
|
153
|
+
return False
|
|
154
|
+
return True
|
|
155
|
+
|
|
156
|
+
def check_types(path: Path, config: Path) -> bool:
|
|
157
|
+
# Detect mypy/pyright
|
|
158
|
+
if (config / "pyproject.toml").exists():
|
|
159
|
+
# Check for mypy config
|
|
160
|
+
result = run(["mypy", str(path)])
|
|
161
|
+
if result.returncode != 0:
|
|
162
|
+
print(f"Type errors: {result.stdout}")
|
|
163
|
+
return False
|
|
164
|
+
return True
|
|
165
|
+
|
|
166
|
+
def check_lint(path: Path) -> bool:
|
|
167
|
+
result = run(["ruff", "check", str(path)])
|
|
168
|
+
if result.returncode != 0:
|
|
169
|
+
print(f"Lint errors: {result.stdout}")
|
|
170
|
+
return False
|
|
171
|
+
return True
|
|
172
|
+
|
|
173
|
+
def check_format(path: Path) -> bool:
|
|
174
|
+
result = run(["ruff", "format", "--check", str(path)])
|
|
175
|
+
if result.returncode != 0:
|
|
176
|
+
print(f"Format issues: {result.stdout}")
|
|
177
|
+
return False
|
|
178
|
+
return True
|
|
179
|
+
|
|
180
|
+
def run_tests(path: Path) -> bool:
|
|
181
|
+
result = run(["pytest", str(path), "-v"])
|
|
182
|
+
if result.returncode != 0:
|
|
183
|
+
print(f"Test failures: {result.stdout}")
|
|
184
|
+
return False
|
|
185
|
+
return True
|
|
186
|
+
|
|
187
|
+
def main():
|
|
188
|
+
target = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(".")
|
|
189
|
+
all_pass = True
|
|
190
|
+
|
|
191
|
+
all_pass &= check_syntax(target)
|
|
192
|
+
all_pass &= check_types(target, target.parent)
|
|
193
|
+
all_pass &= check_lint(target)
|
|
194
|
+
all_pass &= check_format(target)
|
|
195
|
+
all_pass &= run_tests(target)
|
|
196
|
+
|
|
197
|
+
if all_pass:
|
|
198
|
+
print("✓ All validation checks passed")
|
|
199
|
+
sys.exit(0)
|
|
200
|
+
else:
|
|
201
|
+
print("✗ Validation failed")
|
|
202
|
+
sys.exit(1)
|
|
203
|
+
|
|
204
|
+
if __name__ == "__main__":
|
|
205
|
+
main()
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Integration with Workflow
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
IMPLEMENT
|
|
214
|
+
↓
|
|
215
|
+
REVIEW (manual)
|
|
216
|
+
↓
|
|
217
|
+
VALIDATE (automated — run pipeline)
|
|
218
|
+
↓
|
|
219
|
+
FIX (if any step fails)
|
|
220
|
+
↓
|
|
221
|
+
RE-VALIDATE
|
|
222
|
+
↓
|
|
223
|
+
FINALIZE
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Do not skip validation steps.** Each step catches different issues.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Decision Rules
|
|
231
|
+
|
|
232
|
+
| Situation | Validation Level |
|
|
233
|
+
|-----------|------------------|
|
|
234
|
+
| New module/file | Full pipeline (all 7 steps) |
|
|
235
|
+
| Bug fix | Syntax + Type + Lint + Tests + Security |
|
|
236
|
+
| Refactoring | Syntax + Type + Lint + Tests |
|
|
237
|
+
| Documentation only | Syntax + Lint |
|
|
238
|
+
| Config change | Syntax + Tests |
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Preferred Patterns
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Quick validation (syntax + lint + type)
|
|
246
|
+
python -m py_compile file.py && ruff check file.py && mypy file.py
|
|
247
|
+
|
|
248
|
+
# Full validation with tests
|
|
249
|
+
pytest path/to/tests -v --tb=short && mypy path/ && ruff check path/
|
|
250
|
+
|
|
251
|
+
# CI validation (all steps)
|
|
252
|
+
python -m py_compile src/ && mypy src/ && ruff check src/ && ruff format --check src/ && pytest tests/ && bandit -r src/
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Avoid
|
|
258
|
+
|
|
259
|
+
- Skipping validation steps (each catches different issues)
|
|
260
|
+
- Claiming "tested" without running tests
|
|
261
|
+
- Running only syntax check
|
|
262
|
+
- Not using project's configured tools
|
|
263
|
+
- Ignoring validation failures
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Related Skills
|
|
268
|
+
|
|
269
|
+
- `generation/workflow.md`
|
|
270
|
+
- `generation/type_hints.md`
|
|
271
|
+
- `generation/error_handling.md`
|
|
272
|
+
- `testing/organization.md`
|
|
273
|
+
- `engineering/pyproject_toml.md`
|
|
274
|
+
- `security/dependency_risks.md`
|