@ranimontagna/agent-toolkit 0.1.6 → 0.1.9
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.
- package/README.md +83 -10
- package/package.json +1 -1
- package/skills/backend/database/postgres-patterns/LICENSE.ANTIGRAVITY +21 -0
- package/skills/backend/database/postgres-patterns/LICENSE.ECC +21 -0
- package/skills/backend/database/postgres-patterns/NOTICE.md +11 -0
- package/skills/backend/database/postgres-patterns/SKILL.md +180 -0
- package/skills/backend/go/golang-patterns/LICENSE +21 -0
- package/skills/backend/go/golang-patterns/NOTICE.md +10 -0
- package/skills/backend/go/golang-patterns/SKILL.md +674 -0
- package/skills/backend/go/golang-testing/LICENSE +21 -0
- package/skills/backend/go/golang-testing/NOTICE.md +10 -0
- package/skills/backend/go/golang-testing/SKILL.md +329 -0
- package/skills/backend/java/java-coding-standards/LICENSE +21 -0
- package/skills/backend/java/java-coding-standards/NOTICE.md +10 -0
- package/skills/backend/java/java-coding-standards/SKILL.md +383 -0
- package/skills/backend/java/java-junit/LICENSE +21 -0
- package/skills/backend/java/java-junit/NOTICE.md +10 -0
- package/skills/backend/java/java-junit/SKILL.md +64 -0
- package/skills/backend/kotlin/kotlin-patterns/LICENSE +21 -0
- package/skills/backend/kotlin/kotlin-patterns/NOTICE.md +7 -0
- package/skills/backend/kotlin/kotlin-patterns/SKILL.md +711 -0
- package/skills/backend/kotlin/kotlin-testing/LICENSE +21 -0
- package/skills/backend/kotlin/kotlin-testing/NOTICE.md +7 -0
- package/skills/backend/kotlin/kotlin-testing/SKILL.md +824 -0
- package/skills/backend/python/python-patterns/LICENSE +21 -0
- package/skills/backend/python/python-patterns/NOTICE.md +7 -0
- package/skills/backend/python/python-patterns/SKILL.md +424 -0
- package/skills/backend/python/python-testing/LICENSE +21 -0
- package/skills/backend/python/python-testing/NOTICE.md +7 -0
- package/skills/backend/python/python-testing/SKILL.md +494 -0
- package/skills/devops/docker-patterns/LICENSE.ANTIGRAVITY +21 -0
- package/skills/devops/docker-patterns/LICENSE.ECC +21 -0
- package/skills/devops/docker-patterns/NOTICE.md +11 -0
- package/skills/devops/docker-patterns/SKILL.md +397 -0
- package/skills/frontend/accessibility/LICENSE +21 -0
- package/skills/frontend/accessibility/NOTICE.md +10 -0
- package/skills/frontend/accessibility/SKILL.md +145 -0
- package/skills/frontend/design/ui-ux-pro-max/LICENSE +21 -0
- package/skills/frontend/design/ui-ux-pro-max/NOTICE.md +12 -0
- package/skills/frontend/design/ui-ux-pro-max/SKILL.md +672 -0
- package/skills/frontend/design/ui-ux-pro-max/data/_sync_all.py +414 -0
- package/skills/frontend/design/ui-ux-pro-max/data/app-interface.csv +31 -0
- package/skills/frontend/design/ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/frontend/design/ui-ux-pro-max/data/colors.csv +162 -0
- package/skills/frontend/design/ui-ux-pro-max/data/design.csv +1776 -0
- package/skills/frontend/design/ui-ux-pro-max/data/draft.csv +1779 -0
- package/skills/frontend/design/ui-ux-pro-max/data/google-fonts.csv +1924 -0
- package/skills/frontend/design/ui-ux-pro-max/data/icons.csv +106 -0
- package/skills/frontend/design/ui-ux-pro-max/data/landing.csv +35 -0
- package/skills/frontend/design/ui-ux-pro-max/data/products.csv +162 -0
- package/skills/frontend/design/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/angular.csv +51 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/laravel.csv +51 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/threejs.csv +54 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/frontend/design/ui-ux-pro-max/data/styles.csv +85 -0
- package/skills/frontend/design/ui-ux-pro-max/data/typography.csv +74 -0
- package/skills/frontend/design/ui-ux-pro-max/data/ui-reasoning.csv +162 -0
- package/skills/frontend/design/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/frontend/design/ui-ux-pro-max/scripts/core.py +262 -0
- package/skills/frontend/design/ui-ux-pro-max/scripts/design_system.py +1148 -0
- package/skills/frontend/design/ui-ux-pro-max/scripts/search.py +114 -0
- package/skills/frontend/react/react-patterns/SKILL.md +4 -4
- package/skills/frontend/react/react-patterns/rules/react/LICENSE +21 -0
- package/skills/frontend/react/react-patterns/rules/react/NOTICE.md +11 -0
- package/skills/frontend/react/react-patterns/rules/react/coding-style.md +109 -0
- package/skills/frontend/react/react-patterns/rules/react/hooks.md +187 -0
- package/skills/frontend/react/react-patterns/rules/react/patterns.md +194 -0
- package/skills/frontend/react/react-patterns/rules/react/security.md +180 -0
- package/skills/frontend/react/react-patterns/rules/react/testing.md +208 -0
- package/skills/frontend/react/react-performance/SKILL.md +2 -2
- package/skills/frontend/react/react-performance/rules/react/LICENSE +21 -0
- package/skills/frontend/react/react-performance/rules/react/NOTICE.md +11 -0
- package/skills/frontend/react/react-performance/rules/react/coding-style.md +109 -0
- package/skills/frontend/react/react-performance/rules/react/hooks.md +187 -0
- package/skills/frontend/react/react-performance/rules/react/patterns.md +194 -0
- package/skills/frontend/react/react-performance/rules/react/security.md +180 -0
- package/skills/frontend/react/react-performance/rules/react/testing.md +208 -0
- package/skills/frontend/react/react-testing/SKILL.md +4 -4
- package/skills/frontend/react/react-testing/rules/react/LICENSE +21 -0
- package/skills/frontend/react/react-testing/rules/react/NOTICE.md +11 -0
- package/skills/frontend/react/react-testing/rules/react/coding-style.md +109 -0
- package/skills/frontend/react/react-testing/rules/react/hooks.md +187 -0
- package/skills/frontend/react/react-testing/rules/react/patterns.md +194 -0
- package/skills/frontend/react/react-testing/rules/react/security.md +180 -0
- package/skills/frontend/react/react-testing/rules/react/testing.md +208 -0
- package/skills/general/code-reviewer/AGENTS.md +292 -0
- package/skills/general/code-reviewer/LICENSE +201 -0
- package/skills/general/code-reviewer/NOTICE.md +10 -0
- package/skills/general/code-reviewer/SKILL.md +132 -0
- package/skills/general/code-reviewer/rules/correctness-error-handling.md +279 -0
- package/skills/general/code-reviewer/rules/maintainability-naming.md +149 -0
- package/skills/general/code-reviewer/rules/maintainability-type-hints.md +93 -0
- package/skills/general/code-reviewer/rules/performance-n-plus-one.md +250 -0
- package/skills/general/code-reviewer/rules/security-sql-injection.md +142 -0
- package/skills/general/code-reviewer/rules/security-xss-prevention.md +225 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Affaan Mustafa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: python-patterns
|
|
3
|
+
description: Use when writing, reviewing, or refactoring Python code with protocols, dataclasses, context managers, decorators, async/await, type hints, and package organization.
|
|
4
|
+
metadata:
|
|
5
|
+
origin: ECC
|
|
6
|
+
globs: ["**/*.py", "**/*.pyi"]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Python Patterns
|
|
10
|
+
|
|
11
|
+
> This skill provides comprehensive Python patterns extending common design principles with Python-specific idioms.
|
|
12
|
+
|
|
13
|
+
## Protocol (Duck Typing)
|
|
14
|
+
|
|
15
|
+
Use `Protocol` for structural subtyping (duck typing with type hints):
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from typing import Protocol
|
|
19
|
+
|
|
20
|
+
class Repository(Protocol):
|
|
21
|
+
def find_by_id(self, id: str) -> dict | None: ...
|
|
22
|
+
def save(self, entity: dict) -> dict: ...
|
|
23
|
+
|
|
24
|
+
# Any class with these methods satisfies the protocol
|
|
25
|
+
class UserRepository:
|
|
26
|
+
def find_by_id(self, id: str) -> dict | None:
|
|
27
|
+
# implementation
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
def save(self, entity: dict) -> dict:
|
|
31
|
+
# implementation
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
def process_entity(repo: Repository, id: str) -> None:
|
|
35
|
+
entity = repo.find_by_id(id)
|
|
36
|
+
# ... process
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Benefits:**
|
|
40
|
+
- Type safety without inheritance
|
|
41
|
+
- Flexible, loosely coupled code
|
|
42
|
+
- Easy testing and mocking
|
|
43
|
+
|
|
44
|
+
## Dataclasses as DTOs
|
|
45
|
+
|
|
46
|
+
Use `dataclass` for data transfer objects and value objects:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from dataclasses import dataclass, field
|
|
50
|
+
from typing import Optional
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class CreateUserRequest:
|
|
54
|
+
name: str
|
|
55
|
+
email: str
|
|
56
|
+
age: Optional[int] = None
|
|
57
|
+
tags: list[str] = field(default_factory=list)
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True)
|
|
60
|
+
class User:
|
|
61
|
+
"""Immutable user entity"""
|
|
62
|
+
id: str
|
|
63
|
+
name: str
|
|
64
|
+
email: str
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Features:**
|
|
68
|
+
- Auto-generated `__init__`, `__repr__`, `__eq__`
|
|
69
|
+
- `frozen=True` for immutability
|
|
70
|
+
- `field()` for complex defaults
|
|
71
|
+
- Type hints for validation
|
|
72
|
+
|
|
73
|
+
## Context Managers
|
|
74
|
+
|
|
75
|
+
Use context managers (`with` statement) for resource management:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from contextlib import contextmanager
|
|
79
|
+
from typing import Generator
|
|
80
|
+
|
|
81
|
+
@contextmanager
|
|
82
|
+
def database_transaction(db) -> Generator[None, None, None]:
|
|
83
|
+
"""Context manager for database transactions"""
|
|
84
|
+
try:
|
|
85
|
+
yield
|
|
86
|
+
db.commit()
|
|
87
|
+
except Exception:
|
|
88
|
+
db.rollback()
|
|
89
|
+
raise
|
|
90
|
+
|
|
91
|
+
# Usage
|
|
92
|
+
with database_transaction(db):
|
|
93
|
+
db.execute("INSERT INTO users ...")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Class-based context manager:**
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
class FileProcessor:
|
|
100
|
+
def __init__(self, filename: str):
|
|
101
|
+
self.filename = filename
|
|
102
|
+
self.file = None
|
|
103
|
+
|
|
104
|
+
def __enter__(self):
|
|
105
|
+
self.file = open(self.filename, 'r')
|
|
106
|
+
return self.file
|
|
107
|
+
|
|
108
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
109
|
+
if self.file:
|
|
110
|
+
self.file.close()
|
|
111
|
+
return False # Don't suppress exceptions
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Generators
|
|
115
|
+
|
|
116
|
+
Use generators for lazy evaluation and memory-efficient iteration:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
def read_large_file(filename: str):
|
|
120
|
+
"""Generator for reading large files line by line"""
|
|
121
|
+
with open(filename, 'r') as f:
|
|
122
|
+
for line in f:
|
|
123
|
+
yield line.strip()
|
|
124
|
+
|
|
125
|
+
# Memory-efficient processing
|
|
126
|
+
for line in read_large_file('huge.txt'):
|
|
127
|
+
process(line)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Generator expressions:**
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
# Instead of list comprehension
|
|
134
|
+
squares = (x**2 for x in range(1000000)) # Lazy evaluation
|
|
135
|
+
|
|
136
|
+
# Pipeline pattern
|
|
137
|
+
numbers = (x for x in range(100))
|
|
138
|
+
evens = (x for x in numbers if x % 2 == 0)
|
|
139
|
+
squares = (x**2 for x in evens)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Decorators
|
|
143
|
+
|
|
144
|
+
### Function Decorators
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from functools import wraps
|
|
148
|
+
import time
|
|
149
|
+
|
|
150
|
+
def timing(func):
|
|
151
|
+
"""Decorator to measure execution time"""
|
|
152
|
+
@wraps(func)
|
|
153
|
+
def wrapper(*args, **kwargs):
|
|
154
|
+
start = time.time()
|
|
155
|
+
result = func(*args, **kwargs)
|
|
156
|
+
end = time.time()
|
|
157
|
+
print(f"{func.__name__} took {end - start:.2f}s")
|
|
158
|
+
return result
|
|
159
|
+
return wrapper
|
|
160
|
+
|
|
161
|
+
@timing
|
|
162
|
+
def slow_function():
|
|
163
|
+
time.sleep(1)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Class Decorators
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
def singleton(cls):
|
|
170
|
+
"""Decorator to make a class a singleton"""
|
|
171
|
+
instances = {}
|
|
172
|
+
|
|
173
|
+
@wraps(cls)
|
|
174
|
+
def get_instance(*args, **kwargs):
|
|
175
|
+
if cls not in instances:
|
|
176
|
+
instances[cls] = cls(*args, **kwargs)
|
|
177
|
+
return instances[cls]
|
|
178
|
+
|
|
179
|
+
return get_instance
|
|
180
|
+
|
|
181
|
+
@singleton
|
|
182
|
+
class Config:
|
|
183
|
+
pass
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Async/Await
|
|
187
|
+
|
|
188
|
+
### Async Functions
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
import asyncio
|
|
192
|
+
from typing import List
|
|
193
|
+
|
|
194
|
+
async def fetch_user(user_id: str) -> dict:
|
|
195
|
+
"""Async function for I/O-bound operations"""
|
|
196
|
+
await asyncio.sleep(0.1) # Simulate network call
|
|
197
|
+
return {"id": user_id, "name": "Alice"}
|
|
198
|
+
|
|
199
|
+
async def fetch_all_users(user_ids: List[str]) -> List[dict]:
|
|
200
|
+
"""Concurrent execution with asyncio.gather"""
|
|
201
|
+
tasks = [fetch_user(uid) for uid in user_ids]
|
|
202
|
+
return await asyncio.gather(*tasks)
|
|
203
|
+
|
|
204
|
+
# Run async code
|
|
205
|
+
asyncio.run(fetch_all_users(["1", "2", "3"]))
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Async Context Managers
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
class AsyncDatabase:
|
|
212
|
+
async def __aenter__(self):
|
|
213
|
+
await self.connect()
|
|
214
|
+
return self
|
|
215
|
+
|
|
216
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
217
|
+
await self.disconnect()
|
|
218
|
+
|
|
219
|
+
async with AsyncDatabase() as db:
|
|
220
|
+
await db.query("SELECT * FROM users")
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Type Hints
|
|
224
|
+
|
|
225
|
+
### Advanced Type Hints
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from typing import TypeVar, Generic, Callable, ParamSpec, Concatenate
|
|
229
|
+
|
|
230
|
+
T = TypeVar('T')
|
|
231
|
+
P = ParamSpec('P')
|
|
232
|
+
|
|
233
|
+
class Repository(Generic[T]):
|
|
234
|
+
"""Generic repository pattern"""
|
|
235
|
+
def __init__(self, entity_type: type[T]):
|
|
236
|
+
self.entity_type = entity_type
|
|
237
|
+
|
|
238
|
+
def find_by_id(self, id: str) -> T | None:
|
|
239
|
+
# implementation
|
|
240
|
+
pass
|
|
241
|
+
|
|
242
|
+
# Type-safe decorator
|
|
243
|
+
def log_call(func: Callable[P, T]) -> Callable[P, T]:
|
|
244
|
+
@wraps(func)
|
|
245
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
246
|
+
print(f"Calling {func.__name__}")
|
|
247
|
+
return func(*args, **kwargs)
|
|
248
|
+
return wrapper
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Union Types (Python 3.10+)
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
def process(value: str | int | None) -> str:
|
|
255
|
+
match value:
|
|
256
|
+
case str():
|
|
257
|
+
return value.upper()
|
|
258
|
+
case int():
|
|
259
|
+
return str(value)
|
|
260
|
+
case None:
|
|
261
|
+
return "empty"
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Dependency Injection
|
|
265
|
+
|
|
266
|
+
### Constructor Injection
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
class UserService:
|
|
270
|
+
def __init__(
|
|
271
|
+
self,
|
|
272
|
+
repository: Repository,
|
|
273
|
+
logger: Logger,
|
|
274
|
+
cache: Cache | None = None
|
|
275
|
+
):
|
|
276
|
+
self.repository = repository
|
|
277
|
+
self.logger = logger
|
|
278
|
+
self.cache = cache
|
|
279
|
+
|
|
280
|
+
def get_user(self, user_id: str) -> User | None:
|
|
281
|
+
if self.cache:
|
|
282
|
+
cached = self.cache.get(user_id)
|
|
283
|
+
if cached:
|
|
284
|
+
return cached
|
|
285
|
+
|
|
286
|
+
user = self.repository.find_by_id(user_id)
|
|
287
|
+
if user and self.cache:
|
|
288
|
+
self.cache.set(user_id, user)
|
|
289
|
+
|
|
290
|
+
return user
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Package Organization
|
|
294
|
+
|
|
295
|
+
### Project Structure
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
project/
|
|
299
|
+
├── src/
|
|
300
|
+
│ └── mypackage/
|
|
301
|
+
│ ├── __init__.py
|
|
302
|
+
│ ├── domain/ # Business logic
|
|
303
|
+
│ │ ├── __init__.py
|
|
304
|
+
│ │ └── models.py
|
|
305
|
+
│ ├── services/ # Application services
|
|
306
|
+
│ │ ├── __init__.py
|
|
307
|
+
│ │ └── user_service.py
|
|
308
|
+
│ └── infrastructure/ # External dependencies
|
|
309
|
+
│ ├── __init__.py
|
|
310
|
+
│ └── database.py
|
|
311
|
+
├── tests/
|
|
312
|
+
│ ├── unit/
|
|
313
|
+
│ └── integration/
|
|
314
|
+
├── pyproject.toml
|
|
315
|
+
└── README.md
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Module Exports
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
# __init__.py
|
|
322
|
+
from .models import User, Product
|
|
323
|
+
from .services import UserService
|
|
324
|
+
|
|
325
|
+
__all__ = ['User', 'Product', 'UserService']
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Error Handling
|
|
329
|
+
|
|
330
|
+
### Custom Exceptions
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
class DomainError(Exception):
|
|
334
|
+
"""Base exception for domain errors"""
|
|
335
|
+
pass
|
|
336
|
+
|
|
337
|
+
class UserNotFoundError(DomainError):
|
|
338
|
+
"""Raised when user is not found"""
|
|
339
|
+
def __init__(self, user_id: str):
|
|
340
|
+
self.user_id = user_id
|
|
341
|
+
super().__init__(f"User {user_id} not found")
|
|
342
|
+
|
|
343
|
+
class ValidationError(DomainError):
|
|
344
|
+
"""Raised when validation fails"""
|
|
345
|
+
def __init__(self, field: str, message: str):
|
|
346
|
+
self.field = field
|
|
347
|
+
self.message = message
|
|
348
|
+
super().__init__(f"{field}: {message}")
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Exception Groups (Python 3.11+)
|
|
352
|
+
|
|
353
|
+
```python
|
|
354
|
+
try:
|
|
355
|
+
# Multiple operations
|
|
356
|
+
pass
|
|
357
|
+
except* ValueError as eg:
|
|
358
|
+
# Handle all ValueError instances
|
|
359
|
+
for exc in eg.exceptions:
|
|
360
|
+
print(f"ValueError: {exc}")
|
|
361
|
+
except* TypeError as eg:
|
|
362
|
+
# Handle all TypeError instances
|
|
363
|
+
for exc in eg.exceptions:
|
|
364
|
+
print(f"TypeError: {exc}")
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Property Decorators
|
|
368
|
+
|
|
369
|
+
```python
|
|
370
|
+
class User:
|
|
371
|
+
def __init__(self, name: str):
|
|
372
|
+
self._name = name
|
|
373
|
+
self._email = None
|
|
374
|
+
|
|
375
|
+
@property
|
|
376
|
+
def name(self) -> str:
|
|
377
|
+
"""Read-only property"""
|
|
378
|
+
return self._name
|
|
379
|
+
|
|
380
|
+
@property
|
|
381
|
+
def email(self) -> str | None:
|
|
382
|
+
return self._email
|
|
383
|
+
|
|
384
|
+
@email.setter
|
|
385
|
+
def email(self, value: str) -> None:
|
|
386
|
+
if '@' not in value:
|
|
387
|
+
raise ValueError("Invalid email")
|
|
388
|
+
self._email = value
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## Functional Programming
|
|
392
|
+
|
|
393
|
+
### Higher-Order Functions
|
|
394
|
+
|
|
395
|
+
```python
|
|
396
|
+
from functools import reduce
|
|
397
|
+
from typing import Callable, TypeVar
|
|
398
|
+
|
|
399
|
+
T = TypeVar('T')
|
|
400
|
+
U = TypeVar('U')
|
|
401
|
+
|
|
402
|
+
def pipe(*functions: Callable) -> Callable:
|
|
403
|
+
"""Compose functions left to right"""
|
|
404
|
+
def inner(arg):
|
|
405
|
+
return reduce(lambda x, f: f(x), functions, arg)
|
|
406
|
+
return inner
|
|
407
|
+
|
|
408
|
+
# Usage
|
|
409
|
+
process = pipe(
|
|
410
|
+
str.strip,
|
|
411
|
+
str.lower,
|
|
412
|
+
lambda s: s.replace(' ', '_')
|
|
413
|
+
)
|
|
414
|
+
result = process(" Hello World ") # "hello_world"
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## When to Use This Skill
|
|
418
|
+
|
|
419
|
+
- Designing Python APIs and packages
|
|
420
|
+
- Implementing async/concurrent systems
|
|
421
|
+
- Structuring Python projects
|
|
422
|
+
- Writing Pythonic code
|
|
423
|
+
- Refactoring Python codebases
|
|
424
|
+
- Type-safe Python development
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Affaan Mustafa
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|