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,276 @@
1
+ # Generation: Error Handling
2
+
3
+ **Purpose**: Consistent, safe error handling patterns for code generation.
4
+
5
+ **When to use**: All code generation. Error handling is critical for correctness.
6
+
7
+ ---
8
+
9
+ ## Core Rules
10
+
11
+ ### Exception Hierarchy
12
+ ```
13
+ BaseException
14
+ ├── KeyboardInterrupt
15
+ ├── SystemExit
16
+ ├── GeneratorExit
17
+ └── Exception
18
+ ├── StopIteration
19
+ ├── StopAsyncIteration
20
+ ├── ArithmeticError
21
+ │ ├── ZeroDivisionError
22
+ │ └── ...
23
+ ├── AssertionError
24
+ ├── AttributeError
25
+ ├── BufferError
26
+ ├── EOFError
27
+ ├── ImportError
28
+ │ └── ModuleNotFoundError
29
+ ├── LookupError
30
+ │ ├── IndexError
31
+ │ └── KeyError
32
+ ├── MemoryError
33
+ ├── NameError
34
+ │ └── UnboundLocalError
35
+ ├── OSError
36
+ │ ├── BlockingIOError
37
+ │ ├── ChildProcessError
38
+ │ ├── ConnectionError
39
+ │ ├── FileExistsError
40
+ │ ├── FileNotFoundError
41
+ │ ├── InterruptedError
42
+ │ ├── IsADirectoryError
43
+ │ ├── NotADirectoryError
44
+ │ ├── PermissionError
45
+ │ ├── ProcessLookupError
46
+ │ └── TimeoutError
47
+ ├── ReferenceError
48
+ ├── RuntimeError
49
+ │ ├── NotImplementedError
50
+ │ └── RecursionError
51
+ ├── SyntaxError
52
+ │ └── IndentationError
53
+ ├── SystemError
54
+ ├── TypeError
55
+ ├── ValueError
56
+ │ └── UnicodeError
57
+ └── Warning
58
+ ```
59
+
60
+ ### Catch Specific Exceptions
61
+ ```python
62
+ # GOOD — specific
63
+ try:
64
+ data = json.loads(text)
65
+ except json.JSONDecodeError as e:
66
+ logger.error("Invalid JSON", extra={"error": str(e), "pos": e.pos})
67
+ raise ValueError("Invalid JSON input") from e
68
+
69
+ # GOOD — tuple of related
70
+ try:
71
+ response = requests.get(url, timeout=5)
72
+ except (requests.Timeout, requests.ConnectionError) as e:
73
+ logger.warning("Request failed", extra={"url": url, "error": str(e)})
74
+ raise ServiceUnavailable("Service unreachable") from e
75
+
76
+ # BAD — bare except
77
+ try:
78
+ ...
79
+ except:
80
+ ... # Catches KeyboardInterrupt, SystemExit!
81
+
82
+ # BAD — broad Exception
83
+ try:
84
+ ...
85
+ except Exception:
86
+ ... # Swallows everything, hard to debug
87
+ ```
88
+
89
+ ### Exception Chaining
90
+ ```python
91
+ # Explicit chaining (preserves original traceback)
92
+ try:
93
+ risky()
94
+ except OriginalError as e:
95
+ raise NewError("Context") from e
96
+
97
+ # Implicit chaining (automatic when raising in except)
98
+ try:
99
+ risky()
100
+ except OriginalError:
101
+ raise NewError("Context") # __context__ set automatically
102
+
103
+ # Suppress chaining
104
+ try:
105
+ risky()
106
+ except OriginalError:
107
+ raise NewError("Context") from None
108
+ ```
109
+
110
+ ### Custom Exceptions
111
+ ```python
112
+ # Domain-specific exceptions
113
+ class DomainError(Exception):
114
+ """Base for domain errors."""
115
+ def __init__(self, message: str, code: str, details: dict | None = None):
116
+ super().__init__(message)
117
+ self.code = code
118
+ self.details = details or {}
119
+
120
+ class ValidationError(DomainError):
121
+ def __init__(self, field: str, message: str):
122
+ super().__init__(message, "VALIDATION_ERROR", {"field": field})
123
+
124
+ class NotFoundError(DomainError):
125
+ def __init__(self, resource: str, id: str):
126
+ super().__init__(f"{resource} not found: {id}", "NOT_FOUND", {"resource": resource, "id": id})
127
+
128
+ class ConflictError(DomainError):
129
+ pass
130
+
131
+ # Usage
132
+ raise ValidationError("email", "Invalid format")
133
+ raise NotFoundError("User", "123")
134
+ ```
135
+
136
+ ### Error Categories (For Handling Strategy)
137
+
138
+ | Category | Examples | Handling |
139
+ |----------|----------|----------|
140
+ | Expected operational failure | `NotFoundError`, `ValidationError`, `ConflictError` | Handle explicitly, return error result |
141
+ | Programming bug | `AssertionError`, `TypeError`, `IndexError` | Let crash, fix code |
142
+ | Invalid external input | `ValueError`, `JSONDecodeError` | Validate early, return 400 |
143
+ | Configuration failure | `KeyError` (missing config), `ImproperlyConfigured` | Fail fast at startup |
144
+ | System failure | `OSError`, `MemoryError`, `ConnectionError` | Retry, circuit breaker, degrade |
145
+
146
+ ### Result Pattern (Alternative to Exceptions)
147
+ ```python
148
+ from dataclasses import dataclass
149
+ from typing import Generic, TypeVar
150
+
151
+ T = TypeVar("T")
152
+ E = TypeVar("E", bound=Exception)
153
+
154
+ @dataclass(frozen=True)
155
+ class Result(Generic[T, E]):
156
+ value: T | None = None
157
+ error: E | None = None
158
+
159
+ @property
160
+ def is_ok(self) -> bool:
161
+ return self.error is None
162
+
163
+ @property
164
+ def is_err(self) -> bool:
165
+ return self.error is not None
166
+
167
+ def unwrap(self) -> T:
168
+ if self.error:
169
+ raise self.error
170
+ return self.value
171
+
172
+ def map[U](self, func: Callable[[T], U]) -> "Result[U, E]":
173
+ if self.error:
174
+ return Result(error=self.error)
175
+ try:
176
+ return Result(value=func(self.value))
177
+ except Exception as e:
178
+ return Result(error=e)
179
+
180
+ # Usage
181
+ def parse_int(s: str) -> Result[int, ValueError]:
182
+ try:
183
+ return Result(value=int(s))
184
+ except ValueError as e:
185
+ return Result(error=e)
186
+
187
+ result = parse_int("42")
188
+ if result.is_ok:
189
+ print(result.value)
190
+ else:
191
+ print(f"Error: {result.error}")
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Decision Rules
197
+
198
+ | Situation | Pattern |
199
+ |-----------|---------|
200
+ | Expected failure (validation, not found) | Custom exception or `Result` |
201
+ | Programming bug | `assert` or let built-in raise |
202
+ | External API failure | Custom exception wrapping original |
203
+ | Retryable failure | Catch specific, retry with backoff |
204
+ | Cleanup needed | `try/finally` or context manager |
205
+ | Multiple independent failures | `ExceptionGroup` (3.11+) |
206
+
207
+ ---
208
+
209
+ ## Preferred Patterns
210
+
211
+ ```python
212
+ # Validation at boundaries
213
+ def create_user(data: dict) -> User:
214
+ # Validate input early
215
+ email = data.get("email")
216
+ if not email or "@" not in email:
217
+ raise ValidationError("email", "Invalid email format")
218
+
219
+ # Business logic
220
+ if user_repo.exists(email):
221
+ raise ConflictError("User already exists")
222
+
223
+ return user_repo.save(User(email=email))
224
+
225
+ # Graceful degradation
226
+ async def get_user_profile(user_id: str) -> UserProfile:
227
+ try:
228
+ return await user_service.get_profile(user_id)
229
+ except UserService.Unavailable:
230
+ # Fallback to cache
231
+ return await cache.get_profile(user_id)
232
+ except UserService.NotFound:
233
+ raise NotFoundError("User", user_id)
234
+
235
+ # Structured error responses (API)
236
+ def handle_error(e: Exception) -> ErrorResponse:
237
+ if isinstance(e, ValidationError):
238
+ return ErrorResponse(400, e.code, e.details)
239
+ if isinstance(e, NotFoundError):
240
+ return ErrorResponse(404, e.code, e.details)
241
+ if isinstance(e, ConflictError):
242
+ return ErrorResponse(409, e.code, e.details)
243
+ logger.exception("Unhandled error")
244
+ return ErrorResponse(500, "INTERNAL_ERROR", {})
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Avoid
250
+
251
+ - Bare `except:` or `except Exception:`
252
+ - Swallowing exceptions silently
253
+ - Using exceptions for control flow (except EAFP)
254
+ - Custom exceptions without `__init__` for context
255
+ - Raising generic `Exception` or `RuntimeError`
256
+ - Losing original exception context (use `from e`)
257
+ - Catching `KeyboardInterrupt` / `SystemExit` (unless shutting down)
258
+
259
+ ---
260
+
261
+ ## Validation Considerations
262
+
263
+ - Test error paths explicitly
264
+ - Verify exception messages don't leak secrets
265
+ - Check logging includes context for debugging
266
+ - Ensure `Result` pattern doesn't hide errors
267
+
268
+ ---
269
+
270
+ ## Related Skills
271
+
272
+ - `generation/workflow.md`
273
+ - `generation/async_concurrency.md` (async errors)
274
+ - `security/input_validation.md`
275
+ - `testing/edge_cases.md`
276
+ - `quality/functions.md`
@@ -0,0 +1,243 @@
1
+ # Generation: Protocols and Generics
2
+
3
+ **Purpose**: Advanced typing with protocols, generics, and variance.
4
+
5
+ **When to use**: Designing flexible, decoupled interfaces and reusable components.
6
+
7
+ ---
8
+
9
+ ## Core Rules
10
+
11
+ ### Protocols (Structural Subtyping)
12
+ ```python
13
+ from typing import Protocol, runtime_checkable
14
+
15
+ # Basic protocol
16
+ class Serializable(Protocol):
17
+ def to_json(self) -> str: ...
18
+ def to_bytes(self) -> bytes: ...
19
+
20
+ # With generics
21
+ T = TypeVar("T")
22
+
23
+ class Repository(Protocol[T]):
24
+ def get(self, id: str) -> T: ...
25
+ def save(self, entity: T) -> None: ...
26
+ def delete(self, id: str) -> bool: ...
27
+
28
+ # Runtime checkable (for isinstance)
29
+ @runtime_checkable
30
+ class Configurable(Protocol):
31
+ def configure(self, settings: dict) -> None: ...
32
+
33
+ # Multiple protocols
34
+ class Service(Repository[User], Configurable, Protocol):
35
+ def start(self) -> None: ...
36
+ ```
37
+
38
+ ### Protocol vs ABC
39
+ | Feature | Protocol | ABC |
40
+ |---------|----------|-----|
41
+ | Inheritance required | No | Yes |
42
+ | Runtime isinstance | Only `@runtime_checkable` | Yes |
43
+ | Multiple implementations | Easy | Requires inheritance |
44
+ | Third-party classes | Works if structure matches | Must subclass |
45
+ | Method enforcement | Static only | Static + runtime |
46
+
47
+ **Prefer Protocol** for interfaces unless runtime checks needed.
48
+
49
+ ### Generic Classes
50
+ ```python
51
+ from typing import Generic, TypeVar
52
+
53
+ T = TypeVar("T")
54
+ K = TypeVar("K")
55
+ V = TypeVar("V")
56
+
57
+ class Box(Generic[T]):
58
+ def __init__(self, value: T) -> None:
59
+ self._value = value
60
+
61
+ def get(self) -> T:
62
+ return self._value
63
+
64
+ def map[U](self, func: Callable[[T], U]) -> Box[U]:
65
+ return Box(func(self._value))
66
+
67
+ # Multiple type vars
68
+ class Pair(Generic[T, U]):
69
+ def __init__(self, first: T, second: U) -> None:
70
+ self.first = first
71
+ self.second = second
72
+ ```
73
+
74
+ ### Variance (Covariance/Contravariance)
75
+ ```python
76
+ from typing import TypeVar, Generic, Protocol
77
+
78
+ # Covariant (output only) — use +T
79
+ T_co = TypeVar("T_co", covariant=True)
80
+
81
+ class Producer(Generic[T_co]):
82
+ def produce(self) -> T_co: ...
83
+
84
+ # Contravariant (input only) — use -T
85
+ T_contra = TypeVar("T_contra", contravariant=True)
86
+
87
+ class Consumer(Generic[T_contra]):
88
+ def consume(self, item: T_contra) -> None: ...
89
+
90
+ # Invariant (both) — default
91
+ T = TypeVar("T")
92
+
93
+ class Processor(Generic[T]):
94
+ def process(self, item: T) -> T: ...
95
+ ```
96
+
97
+ ### Variance Rules
98
+ | Position | Variance |
99
+ |----------|----------|
100
+ | Return type | Covariant (+) |
101
+ | Argument type | Contravariant (-) |
102
+ | Mutable attribute | Invariant |
103
+ | Read-only property | Covariant |
104
+
105
+ ### Protocol Variance
106
+ ```python
107
+ T_co = TypeVar("T_co", covariant=True)
108
+
109
+ class Readable(Protocol[T_co]):
110
+ def read(self) -> T_co: ... # Covariant OK
111
+
112
+ T_contra = TypeVar("T_contra", contravariant=True)
113
+
114
+ class Writable(Protocol[T_contra]):
115
+ def write(self, data: T_contra) -> None: ... # Contravariant OK
116
+ ```
117
+
118
+ ### Constrained TypeVars
119
+ ```python
120
+ # Only these types allowed
121
+ T = TypeVar("T", int, float, str)
122
+
123
+ def process(x: T) -> T: # Only int, float, str accepted
124
+ return x
125
+ ```
126
+
127
+ ### Bound TypeVars
128
+ ```python
129
+ # Must be subclass of bound
130
+ T = TypeVar("T", bound="BaseEntity")
131
+
132
+ class BaseEntity:
133
+ id: int
134
+
135
+ def save(entity: T) -> T: # Must be BaseEntity subclass
136
+ return entity
137
+ ```
138
+
139
+ ### Higher-Kinded Types (Simulated)
140
+ ```python
141
+ from typing import TypeVar, Generic, Callable
142
+
143
+ # Functor-like
144
+ F = TypeVar("F", bound=Callable[..., Any])
145
+
146
+ def map_func[F](func: Callable[[A], B], fa: F[A]) -> F[B]: # Not directly expressible
147
+ ...
148
+
149
+ # Use protocols for typeclass-like patterns
150
+ class Functor(Protocol[T]):
151
+ def map[U](self, func: Callable[[T], U]) -> "Functor[U]": ...
152
+ ```
153
+
154
+ ### Type Parameters (Python 3.12+)
155
+ ```python
156
+ # New syntax
157
+ class Box[T]:
158
+ def __init__(self, value: T) -> None:
159
+ self.value = value
160
+
161
+ def get(self) -> T:
162
+ return self.value
163
+
164
+ def identity[T](x: T) -> T:
165
+ return x
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Decision Rules
171
+
172
+ | Need | Pattern |
173
+ |------|---------|
174
+ | Interface for duck typing | `Protocol` |
175
+ | Interface needing `isinstance` | `@runtime_checkable Protocol` |
176
+ | Reusable container | `Generic[T]` |
177
+ | Read-only collection | `Generic[+T]` (covariant) |
178
+ | Callback handler | `Generic[-T]` (contravariant) |
179
+ | Limited type set | `TypeVar("T", A, B, C)` |
180
+ | Subtype constraint | `TypeVar("T", bound=Base)` |
181
+ | Self-returning methods | `Self` (3.11+) |
182
+
183
+ ---
184
+
185
+ ## Preferred Patterns
186
+
187
+ ```python
188
+ # Repository pattern with protocol
189
+ class UserRepo(Protocol):
190
+ def get(self, id: UserID) -> User | None: ...
191
+ def list(self, filter: UserFilter) -> list[User]: ...
192
+ def save(self, user: User) -> User: ...
193
+
194
+ # Generic service
195
+ class CrudService(Generic[T]):
196
+ def __init__(self, repo: Repository[T]) -> None:
197
+ self.repo = repo
198
+
199
+ def get_or_create(self, id: str, factory: Callable[[], T]) -> T:
200
+ if (existing := self.repo.get(id)) is not None:
201
+ return existing
202
+ new = factory()
203
+ self.repo.save(new)
204
+ return new
205
+
206
+ # Covariant read-only view
207
+ class ReadOnlyList(Generic[T_co]):
208
+ def __init__(self, items: list[T_co]) -> None:
209
+ self._items = tuple(items)
210
+
211
+ def __getitem__(self, i: int) -> T_co:
212
+ return self._items[i]
213
+
214
+ def __iter__(self) -> Iterator[T_co]:
215
+ return iter(self._items)
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Avoid
221
+
222
+ - Overusing generics (YAGNI)
223
+ - Invariant generics when covariant/contravariant works
224
+ - `@runtime_checkable` on large protocols (performance)
225
+ - Complex variance without clear need
226
+ - Protocols with too many methods (split them)
227
+
228
+ ---
229
+
230
+ ## Validation Considerations
231
+
232
+ - `mypy --strict` catches variance errors
233
+ - Protocol conformance checked structurally
234
+ - `isinstance(obj, Protocol)` only works with `@runtime_checkable`
235
+
236
+ ---
237
+
238
+ ## Related Skills
239
+
240
+ - `generation/type_hints.md`
241
+ - `core/oop.md` (ABCs)
242
+ - `quality/abstractions.md`
243
+ - `engineering/dependency_management.md`