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.
Files changed (105) hide show
  1. python_skills/__init__.py +10 -0
  2. python_skills/__main__.py +6 -0
  3. python_skills/adapters/__init__.py +48 -0
  4. python_skills/adapters/agent_skills.py +415 -0
  5. python_skills/adapters/aider_adapter.py +226 -0
  6. python_skills/adapters/base.py +153 -0
  7. python_skills/adapters/claude.py +474 -0
  8. python_skills/adapters/cline.py +332 -0
  9. python_skills/adapters/codex.py +24 -0
  10. python_skills/adapters/continue_adapter.py +198 -0
  11. python_skills/adapters/cursor.py +327 -0
  12. python_skills/adapters/gemini.py +26 -0
  13. python_skills/adapters/goose.py +26 -0
  14. python_skills/adapters/junie.py +25 -0
  15. python_skills/adapters/kiro.py +382 -0
  16. python_skills/adapters/opencode.py +27 -0
  17. python_skills/adapters/roo.py +25 -0
  18. python_skills/adapters/universal.py +203 -0
  19. python_skills/adapters/vscode.py +27 -0
  20. python_skills/adapters/windsurf.py +26 -0
  21. python_skills/adapters/zed.py +27 -0
  22. python_skills/cli.py +326 -0
  23. python_skills/config.py +160 -0
  24. python_skills/detector.py +152 -0
  25. python_skills/installer.py +163 -0
  26. python_skills/markers.py +115 -0
  27. python_skills/skills/__init__.py +14 -0
  28. python_skills/skills/loader.py +171 -0
  29. python_skills/skills/metadata.py +152 -0
  30. python_skills/skills/registry.py +101 -0
  31. python_skills/state.py +204 -0
  32. python_skills-1.0.0.dist-info/METADATA +99 -0
  33. python_skills-1.0.0.dist-info/RECORD +105 -0
  34. python_skills-1.0.0.dist-info/WHEEL +4 -0
  35. python_skills-1.0.0.dist-info/entry_points.txt +2 -0
  36. python_skills-1.0.0.dist-info/licenses/LICENSE +21 -0
  37. skills/advanced_python.md +239 -0
  38. skills/anti_patterns/index.md +406 -0
  39. skills/comprehensions.md +167 -0
  40. skills/control_flow.md +175 -0
  41. skills/data_structures.md +243 -0
  42. skills/debugging/common_bugs.md +222 -0
  43. skills/debugging/inspection_techniques.md +249 -0
  44. skills/debugging/root_cause.md +203 -0
  45. skills/engineering/application_logging.md +195 -0
  46. skills/engineering/cli_apps.md +207 -0
  47. skills/engineering/configuration.md +218 -0
  48. skills/engineering/database.md +240 -0
  49. skills/engineering/dependency_management.md +205 -0
  50. skills/engineering/http_clients.md +267 -0
  51. skills/engineering/modules_packages.md +211 -0
  52. skills/engineering/packaging.md +197 -0
  53. skills/engineering/project_structure.md +155 -0
  54. skills/engineering/pyproject_toml.md +302 -0
  55. skills/engineering/virtual_environments.md +206 -0
  56. skills/functions.md +244 -0
  57. skills/generation/async_concurrency.md +291 -0
  58. skills/generation/error_handling.md +276 -0
  59. skills/generation/protocols_generics.md +243 -0
  60. skills/generation/type_hints.md +290 -0
  61. skills/generation/validation_pipeline.md +274 -0
  62. skills/generation/workflow.md +190 -0
  63. skills/oop.md +228 -0
  64. skills/quality/abstractions.md +154 -0
  65. skills/quality/comments.md +177 -0
  66. skills/quality/documentation.md +176 -0
  67. skills/quality/duplication.md +137 -0
  68. skills/quality/maintainability.md +142 -0
  69. skills/quality/naming.md +171 -0
  70. skills/quality/quality_functions.md +245 -0
  71. skills/quality/readability.md +239 -0
  72. skills/quality/type_annotations.md +192 -0
  73. skills/refactoring/behavior_preservation.md +157 -0
  74. skills/refactoring/incremental.md +187 -0
  75. skills/refactoring/interface_stability.md +199 -0
  76. skills/refactoring/safe_refactoring.md +206 -0
  77. skills/security/auth_boundaries.md +200 -0
  78. skills/security/command_injection.md +207 -0
  79. skills/security/dependency_risks.md +282 -0
  80. skills/security/file_handling.md +156 -0
  81. skills/security/input_validation.md +190 -0
  82. skills/security/path_traversal.md +172 -0
  83. skills/security/secrets.md +171 -0
  84. skills/security/sql_injection.md +188 -0
  85. skills/security/unsafe_deserialization.md +164 -0
  86. skills/stdlib/argparse.md +178 -0
  87. skills/stdlib/collections.md +212 -0
  88. skills/stdlib/datetime.md +187 -0
  89. skills/stdlib/functools.md +238 -0
  90. skills/stdlib/itertools.md +183 -0
  91. skills/stdlib/json.md +162 -0
  92. skills/stdlib/logging.md +185 -0
  93. skills/stdlib/os_sys.md +184 -0
  94. skills/stdlib/pathlib.md +218 -0
  95. skills/stdlib/re.md +171 -0
  96. skills/stdlib/statistics.md +112 -0
  97. skills/stdlib/subprocess.md +211 -0
  98. skills/testing/async_tests.md +249 -0
  99. skills/testing/coverage.md +168 -0
  100. skills/testing/edge_cases.md +197 -0
  101. skills/testing/fixtures_mocks.md +203 -0
  102. skills/testing/organization.md +205 -0
  103. skills/testing/parameterized.md +174 -0
  104. skills/testing/regression_tests.md +165 -0
  105. skills/variables_types.md +107 -0
@@ -0,0 +1,192 @@
1
+ # Quality: Type Annotations
2
+
3
+ **Purpose**: Appropriate type hints — useful, not noise.
4
+
5
+ **When to use**: All code generation. Quality type hints improve maintainability.
6
+
7
+ ---
8
+
9
+ ## Core Rules
10
+
11
+ ### When to Annotate
12
+ | Element | Annotate? |
13
+ |---------|-----------|
14
+ | Public function signature | Yes |
15
+ | Public method signature | Yes |
16
+ | Class attributes | Yes |
17
+ | Module-level constants | Yes |
18
+ | Local variables | Usually no (inference) |
19
+ | Loop variables | No |
20
+ | Trivial helpers | Optional |
21
+
22
+ ### Useful vs Noise
23
+
24
+ ```python
25
+ # USEFUL — public API, complex types
26
+ def fetch_users(
27
+ client: APIClient,
28
+ filters: UserFilters | None = None,
29
+ limit: int = 100,
30
+ ) -> list[User]:
31
+ ...
32
+
33
+ # USEFUL — generic class
34
+ class Repository(Generic[T]):
35
+ def get(self, id: str) -> T | None: ...
36
+
37
+ # NOISE — obvious inference
38
+ count: int = 0
39
+ name: str = "default"
40
+ items: list[str] = []
41
+ for i, item in enumerate(items): # i inferred as int
42
+ ...
43
+
44
+ # NOISE — over-specified
45
+ def add(a: int, b: int) -> int:
46
+ return a + b
47
+ ```
48
+
49
+ ### Type Hint Style
50
+ ```python
51
+ # Python 3.9+ — prefer built-in generics
52
+ list[str]
53
+ dict[str, int]
54
+ set[int]
55
+ tuple[int, str]
56
+ tuple[int, ...] # variable length
57
+
58
+ # Union — Python 3.10+
59
+ int | str
60
+ list[int | str]
61
+
62
+ # Optional
63
+ str | None
64
+
65
+ # Callable
66
+ Callable[[int, str], bool]
67
+ # Or collections.abc.Callable
68
+
69
+ # Type alias (3.12+)
70
+ type UserID = int
71
+ type JSONValue = str | int | float | bool | None | list["JSONValue"] | dict[str, "JSONValue"]
72
+ ```
73
+
74
+ ### Strictness Levels
75
+ ```toml
76
+ # pyproject.toml — mypy config
77
+ [tool.mypy]
78
+ # Strict (recommended for new projects)
79
+ strict = true
80
+ warn_return_any = true
81
+ warn_unused_configs = true
82
+ disallow_untyped_defs = true
83
+ disallow_incomplete_defs = true
84
+ check_untyped_defs = true
85
+ no_implicit_optional = true
86
+
87
+ # Gradual adoption — per module
88
+ [[tool.mypy.overrides]]
89
+ module = "legacy.*"
90
+ disallow_untyped_defs = false
91
+ ```
92
+
93
+ ### TypedDict for External Data
94
+ ```python
95
+ from typing import TypedDict, NotRequired
96
+
97
+ class UserAPIResponse(TypedDict):
98
+ id: int
99
+ name: str
100
+ email: str
101
+ created_at: str # ISO format
102
+ metadata: NotRequired[dict[str, str]] # Optional key
103
+
104
+ def parse_user(data: UserAPIResponse) -> User:
105
+ return User(
106
+ id=data["id"],
107
+ name=data["name"],
108
+ email=data["email"],
109
+ created_at=datetime.fromisoformat(data["created_at"]),
110
+ )
111
+ ```
112
+
113
+ ### Protocol for Interfaces
114
+ ```python
115
+ from typing import Protocol
116
+
117
+ class Cache(Protocol):
118
+ def get(self, key: str) -> bytes | None: ...
119
+ def set(self, key: str, value: bytes, ttl: int) -> None: ...
120
+
121
+ # Any object with get/set implements Cache (no inheritance needed)
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Decision Rules
127
+
128
+ | Situation | Annotation Level |
129
+ |-----------|------------------|
130
+ | New project | Strict (`mypy --strict`) |
131
+ | Existing project | Match project config |
132
+ | Public library | Full annotations + `py.typed` |
133
+ | Internal app | Public API annotated, internal inferred |
134
+ | Prototyping | Minimal |
135
+
136
+ ---
137
+
138
+ ## Preferred Patterns
139
+
140
+ ```python
141
+ # Function with full hints
142
+ def process_order(
143
+ order: Order,
144
+ inventory: InventoryService,
145
+ payment: PaymentGateway,
146
+ *,
147
+ idempotency_key: str | None = None,
148
+ ) -> OrderResult:
149
+ ...
150
+
151
+ # Class with typed attributes
152
+ class Config:
153
+ database_url: str
154
+ pool_size: int = 10
155
+ timeout: float = 30.0
156
+ debug: bool = False
157
+
158
+ # Generic with constraints
159
+ T = TypeVar("T", bound=Entity)
160
+
161
+ class Repository(Generic[T]):
162
+ def get(self, id: str) -> T | None: ...
163
+ def list(self) -> list[T]: ...
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Avoid
169
+
170
+ - `Any` without `# type: ignore[...]` justification
171
+ - `object` as "unknown type" (use `Any` or proper protocol)
172
+ - Overly complex nested types without aliases
173
+ - Type hints that are wrong (lying types)
174
+ - Ignoring mypy errors without comment
175
+
176
+ ---
177
+
178
+ ## Validation Considerations
179
+
180
+ - `mypy --strict` passes
181
+ - `pyright` passes
182
+ - No `# type: ignore` without error code
183
+ - `py.typed` marker for libraries
184
+
185
+ ---
186
+
187
+ ## Related Skills
188
+
189
+ - `generation/type_hints.md`
190
+ - `generation/protocols_generics.md`
191
+ - `engineering/pyproject_toml.md`
192
+ - `quality/readability.md`
@@ -0,0 +1,157 @@
1
+ # Refactoring: Behavior Preservation
2
+
3
+ **Purpose**: Ensure refactoring doesn't change observable behavior.
4
+
5
+ **When to use**: Every refactoring, especially complex ones.
6
+
7
+ ---
8
+
9
+ ## Core Rules
10
+
11
+ ### Behavior Definition
12
+ Behavior = **observable outputs for given inputs**
13
+ - Return values
14
+ - Side effects (DB writes, API calls, files, logs)
15
+ - Exceptions raised
16
+ - Timing (if specified in requirements)
17
+
18
+ ### Preservation Techniques
19
+
20
+ #### 1. Characterization Tests (Golden Master)
21
+ ```python
22
+ # Before refactoring, capture current behavior
23
+ def test_order_calculation_golden_master():
24
+ """Characterization test - captures current behavior"""
25
+ test_cases = [
26
+ {"items": [{"price": 10, "qty": 2}], "tax_rate": 0.1},
27
+ {"items": [{"price": 100, "qty": 1}], "tax_rate": 0.0},
28
+ {"items": [], "tax_rate": 0.1},
29
+ # ... 50+ real cases from production
30
+ ]
31
+
32
+ for case in test_cases:
33
+ result = calculate_order_total(case["items"], case["tax_rate"])
34
+ # Save as golden master
35
+ assert result == case["expected"]
36
+ ```
37
+
38
+ #### 2. Property-Based Tests
39
+ ```python
40
+ from hypothesis import given, strategies as st
41
+
42
+ @given(st.lists(st.fixed_dictionaries({
43
+ "price": st.integers(0, 10000),
44
+ "qty": st.integers(1, 100),
45
+ })), st.floats(0, 0.5))
46
+ def test_calculation_properties(items, tax_rate):
47
+ """Properties that must hold after refactoring"""
48
+ result = calculate_order_total(items, tax_rate)
49
+
50
+ # Property: total >= subtotal
51
+ subtotal = sum(i["price"] * i["qty"] for i in items)
52
+ assert result >= subtotal
53
+
54
+ # Property: tax = subtotal * rate (approximately)
55
+ expected_tax = subtotal * tax_rate
56
+ actual_tax = result - subtotal
57
+ assert abs(actual_tax - expected_tax) < 0.01
58
+ ```
59
+
60
+ #### 3. Contract Tests
61
+ ```python
62
+ # Protocol defines contract
63
+ class OrderCalculator(Protocol):
64
+ def calculate(self, items: list[Item], tax_rate: float) -> Decimal: ...
65
+
66
+ # Both implementations must satisfy
67
+ @pytest.fixture(params=[LegacyCalculator, NewCalculator])
68
+ def calculator(request) -> OrderCalculator:
69
+ return request.param()
70
+
71
+ def test_calculator_contract(calculator: OrderCalculator):
72
+ # Same tests for both implementations
73
+ result = calculator.calculate([Item(10, 2)], 0.1)
74
+ assert result == Decimal("22.00")
75
+ ```
76
+
77
+ #### 4. Parallel Run (Production)
78
+ ```python
79
+ # Shadow mode - run both, compare, log differences
80
+ def process_order(order):
81
+ legacy_result = legacy_processor.process(order)
82
+ new_result = new_processor.process(order)
83
+
84
+ if legacy_result != new_result:
85
+ logger.warning(
86
+ "Behavior mismatch",
87
+ legacy=legacy_result,
88
+ new=new_result,
89
+ order_id=order.id,
90
+ )
91
+
92
+ return legacy_result # Still return legacy during transition
93
+ ```
94
+
95
+ ### What Must Be Preserved
96
+ | Aspect | Verify |
97
+ |--------|--------|
98
+ | Return values | Exact equality (or specified tolerance) |
99
+ | Exceptions | Same type, message, context |
100
+ | Side effects | Same DB writes, API calls, files |
101
+ | Timing | Within acceptable bounds |
102
+ | Logs | Same level, structure (optional) |
103
+
104
+ ---
105
+
106
+ ## Decision Rules
107
+
108
+ | Refactor Type | Verification Method |
109
+ |---------------|---------------------|
110
+ | Simple extraction | Existing unit tests |
111
+ | Algorithm change | Property tests + golden master |
112
+ | Implementation swap | Contract tests + shadow mode |
113
+ | Large restructuring | Characterization tests + integration tests |
114
+
115
+ ---
116
+
117
+ ## Preferred Patterns
118
+
119
+ ```python
120
+ # Regression test for every behavior change
121
+ def test_refactor_preserves_bug_fix_123():
122
+ """Ensures refactoring doesn't reintroduce bug #123"""
123
+ # Exact scenario from bug report
124
+ input_data = create_bug_scenario()
125
+
126
+ result = refactored_function(input_data)
127
+
128
+ # Bug was: returned wrong value for edge case
129
+ assert result == expected_correct_value
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Avoid
135
+
136
+ - Assuming "it's the same logic" without verification
137
+ - Deleting characterization tests after refactor
138
+ - Refactoring without any automated verification
139
+ - Changing behavior "while we're at it"
140
+
141
+ ---
142
+
143
+ ## Validation Considerations
144
+
145
+ - Run characterization tests before and after
146
+ - Property tests run on both implementations
147
+ - Shadow mode logs zero mismatches before cutover
148
+ - Integration tests cover full workflows
149
+
150
+ ---
151
+
152
+ ## Related Skills
153
+
154
+ - `refactoring/safe_refactoring.md`
155
+ - `refactoring/incremental.md`
156
+ - `testing/regression_tests.md`
157
+ - `testing/edge_cases.md`
@@ -0,0 +1,187 @@
1
+ # Refactoring: Incremental Changes
2
+
3
+ **Purpose**: Make refactoring safe through small, verifiable increments.
4
+
5
+ **When to use**: Any refactoring larger than a single function extraction.
6
+
7
+ ---
8
+
9
+ ## Core Rules
10
+
11
+ ### Incremental Principles
12
+ 1. **One logical change per commit**
13
+ 2. **Each commit passes all tests**
14
+ 3. **No "temporary" broken state committed**
15
+ 4. **Reviewable diffs** (<200 lines ideal)
16
+
17
+ ### Breaking Down Large Refactors
18
+
19
+ ```python
20
+ # Goal: Replace legacy UserService with NewUserService
21
+
22
+ # Step 1: Create NewUserService with same interface
23
+ class NewUserService:
24
+ def get(self, id): ...
25
+ def create(self, data): ...
26
+
27
+ # Step 2: Add feature flag
28
+ class UserService:
29
+ def __init__(self):
30
+ self.legacy = LegacyUserService()
31
+ self.new = NewUserService()
32
+ self.use_new = settings.use_new_service
33
+
34
+ def get(self, id):
35
+ if self.use_new:
36
+ return self.new.get(id)
37
+ return self.legacy.get(id)
38
+
39
+ def create(self, data):
40
+ if self.use_new:
41
+ return self.new.create(data)
42
+ return self.legacy.create(data)
43
+
44
+ # Step 3: Enable for 1% of users (canary)
45
+ # Step 4: Enable for all
46
+ # Step 5: Remove legacy code
47
+ ```
48
+
49
+ ### Incremental Extraction
50
+ ```python
51
+ # Large function -> small functions (one at a time)
52
+
53
+ # Original: 100-line process() function
54
+
55
+ # Commit 1: Extract validation
56
+ def validate_input(data):
57
+ # ... 20 lines extracted
58
+ pass
59
+
60
+ def process(data):
61
+ validate_input(data) # New call
62
+ # ... 80 lines remain
63
+
64
+ # Commit 2: Extract calculation
65
+ def calculate_totals(items):
66
+ # ... 30 lines extracted
67
+ pass
68
+
69
+ def process(data):
70
+ validate_input(data)
71
+ totals = calculate_totals(data.items) # New call
72
+ # ... 50 lines remain
73
+
74
+ # Commit 3: Extract persistence
75
+ def save_results(data, totals):
76
+ # ... 30 lines extracted
77
+ pass
78
+
79
+ def process(data):
80
+ validate_input(data)
81
+ totals = calculate_totals(data.items)
82
+ save_results(data, totals)
83
+ # ... 20 lines remain (orchestration)
84
+ ```
85
+
86
+ ### Incremental Type Changes
87
+ ```python
88
+ # Change function signature incrementally
89
+
90
+ # Before: func(a, b, c)
91
+ # Goal: func(config: Config)
92
+
93
+ # Step 1: Add config parameter with defaults
94
+ def func(a, b, c, config=None):
95
+ if config:
96
+ a = config.a
97
+ b = config.b
98
+ c = config.c
99
+ # ... rest unchanged
100
+
101
+ # Step 2: Update all callers to pass config
102
+ # Step 3: Make config required
103
+ def func(config: Config):
104
+ # ... use config.a, config.b, config.c
105
+
106
+ # Step 4: Remove old parameters
107
+ ```
108
+
109
+ ### Database Migration (Incremental)
110
+ ```python
111
+ # Add column, migrate data, switch, remove old
112
+
113
+ # Migration 1: Add new column (nullable)
114
+ ALTER TABLE users ADD COLUMN email_normalized VARCHAR(255);
115
+
116
+ # Migration 2: Backfill (batch, with progress)
117
+ UPDATE users SET email_normalized = LOWER(email) WHERE email_normalized IS NULL;
118
+
119
+ # Migration 3: Add index, make not null
120
+ CREATE INDEX idx_users_email_norm ON users(email_normalized);
121
+ ALTER TABLE users ALTER COLUMN email_normalized SET NOT NULL;
122
+
123
+ # Migration 4: Switch application to new column
124
+ # (Deploy code that reads/writes email_normalized)
125
+
126
+ # Migration 5: Drop old column (after verification)
127
+ ALTER TABLE users DROP COLUMN email;
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Decision Rules
133
+
134
+ | Refactor Size | Increments |
135
+ |---------------|------------|
136
+ | Single function | 1-3 commits |
137
+ | Class extraction | 3-10 commits |
138
+ | Module restructure | 10-30 commits |
139
+ | Architecture change | 30+ commits (feature flags) |
140
+
141
+ ---
142
+
143
+ ## Preferred Patterns
144
+
145
+ ```python
146
+ # Commit message template
147
+ # refactor: extract validation from process_order
148
+ #
149
+ # Extracted validate_order() function from process_order()
150
+ # to improve readability and testability.
151
+ # No behavior change.
152
+
153
+ # Git workflow
154
+ git checkout -b refactor/extract-validation
155
+ # ... make change ...
156
+ git add -p # Stage hunks selectively
157
+ git commit -m "refactor: extract validation from process_order"
158
+ # ... run tests ...
159
+ # ... next increment ...
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Avoid
165
+
166
+ - "Refactor everything in one PR"
167
+ - Commits that break tests
168
+ - Mixing refactor + feature + bugfix
169
+ - No feature flag for risky changes
170
+ - Deleting old code before new is verified
171
+
172
+ ---
173
+
174
+ ## Validation Considerations
175
+
176
+ - `git log --oneline` shows clear incremental steps
177
+ - Each commit: `pytest` passes
178
+ - Bisect works (each commit builds)
179
+ - Code review per commit or small PR
180
+
181
+ ---
182
+
183
+ ## Related Skills
184
+
185
+ - `refactoring/safe_refactoring.md`
186
+ - `refactoring/behavior_preservation.md`
187
+ - `testing/regression_tests.md`