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,165 @@
|
|
|
1
|
+
# Testing: Regression Tests
|
|
2
|
+
|
|
3
|
+
**Purpose**: Prevent previously fixed bugs from reappearing.
|
|
4
|
+
|
|
5
|
+
**When to use**: Every bug fix, every behavior change, every refactoring.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Rules
|
|
10
|
+
|
|
11
|
+
### Every Bug Fix = Regression Test
|
|
12
|
+
```python
|
|
13
|
+
# Bug: User creation failed with uppercase email
|
|
14
|
+
# Fix: Normalize email to lowercase
|
|
15
|
+
|
|
16
|
+
def test_user_creation_normalizes_email(user_service):
|
|
17
|
+
"""Regression: Issue #123 - uppercase email caused duplicate"""
|
|
18
|
+
user = user_service.create("USER@EXAMPLE.COM", "Test")
|
|
19
|
+
|
|
20
|
+
assert user.email == "user@example.com"
|
|
21
|
+
|
|
22
|
+
# Duplicate should still fail
|
|
23
|
+
with pytest.raises(ConflictError):
|
|
24
|
+
user_service.create("user@example.com", "Test 2")
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Regression Test Naming
|
|
28
|
+
```python
|
|
29
|
+
def test_issue_123_email_normalization():
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
def test_cve_2024_xxxx_sql_injection_prevented():
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
def test_fix_memory_leak_in_batch_processor():
|
|
36
|
+
...
|
|
37
|
+
|
|
38
|
+
def test_regression_double_submit_idempotency():
|
|
39
|
+
...
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Test Location
|
|
43
|
+
```
|
|
44
|
+
tests/
|
|
45
|
+
├── regression/
|
|
46
|
+
│ ├── test_issue_123_email.py
|
|
47
|
+
│ ├── test_cve_2024_xxxx.py
|
|
48
|
+
│ └── test_pr_456_refactor.py
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Minimal Reproduction
|
|
52
|
+
```python
|
|
53
|
+
# Minimal test that reproduces the exact bug
|
|
54
|
+
def test_issue_456_truncated_unicode():
|
|
55
|
+
"""Regression: PR #456 - unicode truncation corrupted data"""
|
|
56
|
+
# Exact input that caused bug
|
|
57
|
+
input_data = "Hello \ud83d\ude00 World" # Surrogate pair
|
|
58
|
+
|
|
59
|
+
# Should handle gracefully, not corrupt
|
|
60
|
+
result = process_text(input_data)
|
|
61
|
+
|
|
62
|
+
# Verify no corruption
|
|
63
|
+
assert "Hello" in result
|
|
64
|
+
assert "World" in result
|
|
65
|
+
# Original bug: result contained replacement chars or crashed
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Behavior Change Tests
|
|
69
|
+
```python
|
|
70
|
+
# When intentionally changing behavior
|
|
71
|
+
def test_new_email_validation_allows_plus_tags():
|
|
72
|
+
"""Behavior change: Issue #200 - allow plus tags in email"""
|
|
73
|
+
# Old behavior: rejected
|
|
74
|
+
# New behavior: accepts
|
|
75
|
+
user = create_user("user+tag@example.com", "Test")
|
|
76
|
+
assert user.email == "user+tag@example.com"
|
|
77
|
+
|
|
78
|
+
# Document the change
|
|
79
|
+
def test_old_email_validation_rejected_plus_tags():
|
|
80
|
+
"""Old behavior (for reference)"""
|
|
81
|
+
# This test documents what USED to happen
|
|
82
|
+
# Keep for history, mark as xfail
|
|
83
|
+
import pytest
|
|
84
|
+
pytest.xfail("Old behavior - plus tags now allowed")
|
|
85
|
+
|
|
86
|
+
with pytest.raises(ValidationError):
|
|
87
|
+
create_user("user+tag@example.com", "Test")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Refactoring Regression
|
|
91
|
+
```python
|
|
92
|
+
# Before refactoring, capture behavior
|
|
93
|
+
def test_refactor_order_calculation_preserves_results():
|
|
94
|
+
"""Regression: Refactored OrderCalculator must produce identical results"""
|
|
95
|
+
test_cases = load_golden_master("order_calculator_golden.json")
|
|
96
|
+
|
|
97
|
+
for case in test_cases:
|
|
98
|
+
result = OrderCalculator().calculate(case["input"])
|
|
99
|
+
assert result == case["expected"], f"Failed on case: {case['name']}"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Decision Rules
|
|
105
|
+
|
|
106
|
+
| Trigger | Action |
|
|
107
|
+
|---------|--------|
|
|
108
|
+
| Bug reported | Write failing test, fix, test passes |
|
|
109
|
+
| Security issue | Write test for attack vector |
|
|
110
|
+
| Refactoring | Golden master tests / property tests |
|
|
111
|
+
| Behavior change | Test new behavior, document old |
|
|
112
|
+
| Dependency update | Test integration points |
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Preferred Patterns
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
# Golden master for complex refactoring
|
|
120
|
+
def test_parser_golden_master():
|
|
121
|
+
"""Regression: Parser refactor must not change output"""
|
|
122
|
+
inputs = load_test_inputs("parser_inputs.json")
|
|
123
|
+
expected = load_expected_outputs("parser_expected.json")
|
|
124
|
+
|
|
125
|
+
for inp, exp in zip(inputs, expected):
|
|
126
|
+
result = parse(inp)
|
|
127
|
+
assert result == exp, f"Mismatch for input: {inp}"
|
|
128
|
+
|
|
129
|
+
# Property test as regression
|
|
130
|
+
from hypothesis import given, strategies as st
|
|
131
|
+
|
|
132
|
+
@given(st.dictionaries(st.text(), st.integers()))
|
|
133
|
+
def test_config_merge_idempotent(config: dict):
|
|
134
|
+
"""Regression: Config merge should be idempotent"""
|
|
135
|
+
merged_once = merge_configs(config, {})
|
|
136
|
+
merged_twice = merge_configs(merged_once, {})
|
|
137
|
+
assert merged_once == merged_twice
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Avoid
|
|
143
|
+
|
|
144
|
+
- Fixing bug without test
|
|
145
|
+
- Deleting regression tests ("it works now")
|
|
146
|
+
- Tests that don't actually reproduce the bug
|
|
147
|
+
- Refactoring without behavior verification
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Validation Considerations
|
|
152
|
+
|
|
153
|
+
- Run regression suite on every PR
|
|
154
|
+
- Tag regression tests for easy filtering: `pytest -m regression`
|
|
155
|
+
- Golden master files version controlled
|
|
156
|
+
- CI fails if regression tests fail
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Related Skills
|
|
161
|
+
|
|
162
|
+
- `testing/organization.md`
|
|
163
|
+
- `testing/edge_cases.md`
|
|
164
|
+
- `refactoring/safe_refactoring.md`
|
|
165
|
+
- `generation/error_handling.md`
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Core: Variables and Types
|
|
2
|
+
|
|
3
|
+
**Purpose**: Fundamental Python variable and type knowledge for code generation.
|
|
4
|
+
|
|
5
|
+
**When to use**: Always active. Foundation for all Python code generation.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Rules
|
|
10
|
+
|
|
11
|
+
### Variable Assignment
|
|
12
|
+
- Variables are references to objects
|
|
13
|
+
- Assignment binds a name to an object
|
|
14
|
+
- Multiple assignment: `a = b = 1` (same object), `a, b = 1, 2` (tuple unpacking)
|
|
15
|
+
- No declaration needed — assignment creates the variable
|
|
16
|
+
|
|
17
|
+
### Primitive Types
|
|
18
|
+
| Type | Literal | Immutable | Use For |
|
|
19
|
+
|------|---------|-----------|---------|
|
|
20
|
+
| `int` | `42`, `0b101`, `0x2A` | Yes | Whole numbers, arbitrary precision |
|
|
21
|
+
| `float` | `3.14`, `1e-5` | Yes | Decimal numbers (IEEE 754) |
|
|
22
|
+
| `bool` | `True`, `False` | Yes | Logic (subclass of `int`) |
|
|
23
|
+
| `str` | `"text"`, `'text'`, `"""multiline"""` | Yes | Text (Unicode) |
|
|
24
|
+
| `bytes` | `b"data"` | Yes | Binary data |
|
|
25
|
+
| `None` | `None` | Yes | Absence of value |
|
|
26
|
+
|
|
27
|
+
### Type Identity vs Equality
|
|
28
|
+
- `is` — identity (same object in memory)
|
|
29
|
+
- `==` — equality (value comparison)
|
|
30
|
+
- Use `is` only for `None`, `True`, `False`, sentinel objects
|
|
31
|
+
- Never use `is` for strings, numbers, or custom objects
|
|
32
|
+
|
|
33
|
+
### Mutable vs Immutable
|
|
34
|
+
**Immutable**: `int`, `float`, `bool`, `str`, `bytes`, `tuple`, `frozenset`, `None`
|
|
35
|
+
**Mutable**: `list`, `dict`, `set`, `bytearray`, custom objects
|
|
36
|
+
|
|
37
|
+
**Critical**: Mutable objects as default arguments create shared state (see anti-patterns)
|
|
38
|
+
|
|
39
|
+
### Type Inspection
|
|
40
|
+
```python
|
|
41
|
+
type(obj) # Exact type
|
|
42
|
+
isinstance(obj, T) # Type check (supports unions, inheritance)
|
|
43
|
+
hasattr(obj, attr) # Attribute existence
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Decision Rules
|
|
49
|
+
|
|
50
|
+
| Situation | Choice |
|
|
51
|
+
|-----------|--------|
|
|
52
|
+
| Need arbitrary precision integer | `int` (native) |
|
|
53
|
+
| Need exact decimal arithmetic | `decimal.Decimal` |
|
|
54
|
+
| Need fraction arithmetic | `fractions.Fraction` |
|
|
55
|
+
| Text data | `str` |
|
|
56
|
+
| Binary data / protocols | `bytes` |
|
|
57
|
+
| Fixed collection of heterogeneous items | `tuple` or `NamedTuple` / `dataclass` |
|
|
58
|
+
| Ordered, mutable collection | `list` |
|
|
59
|
+
| Key-value mapping | `dict` |
|
|
60
|
+
| Unique items, membership testing | `set` |
|
|
61
|
+
| Immutable unique items | `frozenset` |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Preferred Patterns
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# Type annotation for clarity (optional but recommended)
|
|
69
|
+
count: int = 0
|
|
70
|
+
name: str = "default"
|
|
71
|
+
items: list[str] = []
|
|
72
|
+
mapping: dict[str, int] = {}
|
|
73
|
+
|
|
74
|
+
# Sentinel for "not provided" (not None)
|
|
75
|
+
_SENTINEL = object()
|
|
76
|
+
|
|
77
|
+
def func(arg=_SENTINEL):
|
|
78
|
+
if arg is _SENTINEL:
|
|
79
|
+
arg = compute_default()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Avoid
|
|
85
|
+
|
|
86
|
+
- Using `is` for string/number comparison
|
|
87
|
+
- Treating mutable objects as immutable
|
|
88
|
+
- Assuming `bool` is only `True`/`False` (it's subclass of `int`)
|
|
89
|
+
- Type inspection via `type(obj) == SomeClass` (use `isinstance`)
|
|
90
|
+
- Chained assignment for mutable objects: `a = b = []` (both reference same list)
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Validation Considerations
|
|
95
|
+
|
|
96
|
+
- Type checkers catch many primitive type errors
|
|
97
|
+
- Runtime `isinstance` checks for external input
|
|
98
|
+
- `mypy --strict` catches implicit `Any`
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Related Skills
|
|
103
|
+
|
|
104
|
+
- `core/data_structures.md`
|
|
105
|
+
- `core/functions.md` (mutable defaults)
|
|
106
|
+
- `generation/type_hints.md`
|
|
107
|
+
- `anti_patterns/index.md` (mutable defaults)
|