locus-product-planning 1.1.0 → 1.2.1
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +2 -2
- package/LICENSE +21 -21
- package/README.md +11 -7
- package/agents/engineering/architect-reviewer.md +122 -122
- package/agents/engineering/engineering-manager.md +101 -101
- package/agents/engineering/principal-engineer.md +98 -98
- package/agents/engineering/staff-engineer.md +86 -86
- package/agents/engineering/tech-lead.md +114 -114
- package/agents/executive/ceo-strategist.md +81 -81
- package/agents/executive/cfo-analyst.md +97 -97
- package/agents/executive/coo-operations.md +100 -100
- package/agents/executive/cpo-product.md +104 -104
- package/agents/executive/cto-architect.md +90 -90
- package/agents/product/product-manager.md +70 -70
- package/agents/product/project-manager.md +95 -95
- package/agents/product/qa-strategist.md +132 -132
- package/agents/product/scrum-master.md +70 -70
- package/dist/index.cjs +13012 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{lib/skills-core.d.ts → index.d.cts} +46 -12
- package/dist/index.d.ts +113 -5
- package/dist/index.js +12963 -237
- package/dist/index.js.map +1 -0
- package/package.json +88 -82
- package/skills/01-executive-suite/ceo-strategist/SKILL.md +132 -132
- package/skills/01-executive-suite/cfo-analyst/SKILL.md +187 -187
- package/skills/01-executive-suite/coo-operations/SKILL.md +211 -211
- package/skills/01-executive-suite/cpo-product/SKILL.md +231 -231
- package/skills/01-executive-suite/cto-architect/SKILL.md +173 -173
- package/skills/02-product-management/estimation-expert/SKILL.md +139 -139
- package/skills/02-product-management/product-manager/SKILL.md +265 -265
- package/skills/02-product-management/program-manager/SKILL.md +178 -178
- package/skills/02-product-management/project-manager/SKILL.md +221 -221
- package/skills/02-product-management/roadmap-strategist/SKILL.md +186 -186
- package/skills/02-product-management/scrum-master/SKILL.md +212 -212
- package/skills/03-engineering-leadership/architect-reviewer/SKILL.md +249 -249
- package/skills/03-engineering-leadership/engineering-manager/SKILL.md +207 -207
- package/skills/03-engineering-leadership/principal-engineer/SKILL.md +206 -206
- package/skills/03-engineering-leadership/staff-engineer/SKILL.md +237 -237
- package/skills/03-engineering-leadership/tech-lead/SKILL.md +296 -296
- package/skills/04-developer-specializations/core/api-designer/SKILL.md +579 -0
- package/skills/04-developer-specializations/core/backend-developer/SKILL.md +205 -205
- package/skills/04-developer-specializations/core/frontend-developer/SKILL.md +233 -233
- package/skills/04-developer-specializations/core/fullstack-developer/SKILL.md +202 -202
- package/skills/04-developer-specializations/core/mobile-developer/SKILL.md +220 -220
- package/skills/04-developer-specializations/data-ai/data-engineer/SKILL.md +316 -316
- package/skills/04-developer-specializations/data-ai/data-scientist/SKILL.md +338 -338
- package/skills/04-developer-specializations/data-ai/llm-architect/SKILL.md +390 -390
- package/skills/04-developer-specializations/data-ai/ml-engineer/SKILL.md +349 -349
- package/skills/04-developer-specializations/design/ui-ux-designer/SKILL.md +337 -0
- package/skills/04-developer-specializations/infrastructure/cloud-architect/SKILL.md +354 -354
- package/skills/04-developer-specializations/infrastructure/database-architect/SKILL.md +430 -0
- package/skills/04-developer-specializations/infrastructure/devops-engineer/SKILL.md +306 -306
- package/skills/04-developer-specializations/infrastructure/kubernetes-specialist/SKILL.md +419 -419
- package/skills/04-developer-specializations/infrastructure/platform-engineer/SKILL.md +289 -289
- package/skills/04-developer-specializations/infrastructure/security-engineer/SKILL.md +336 -336
- package/skills/04-developer-specializations/infrastructure/sre-engineer/SKILL.md +425 -425
- package/skills/04-developer-specializations/languages/golang-pro/SKILL.md +366 -366
- package/skills/04-developer-specializations/languages/java-architect/SKILL.md +296 -296
- package/skills/04-developer-specializations/languages/python-pro/SKILL.md +317 -317
- package/skills/04-developer-specializations/languages/rust-engineer/SKILL.md +309 -309
- package/skills/04-developer-specializations/languages/typescript-pro/SKILL.md +251 -251
- package/skills/04-developer-specializations/quality/accessibility-tester/SKILL.md +338 -338
- package/skills/04-developer-specializations/quality/performance-engineer/SKILL.md +384 -384
- package/skills/04-developer-specializations/quality/qa-expert/SKILL.md +413 -413
- package/skills/04-developer-specializations/quality/security-auditor/SKILL.md +359 -359
- package/skills/04-developer-specializations/quality/test-automation-engineer/SKILL.md +711 -0
- package/skills/05-specialists/compliance-specialist/SKILL.md +171 -171
- package/skills/05-specialists/technical-writer/SKILL.md +576 -0
- package/skills/using-locus/SKILL.md +5 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/skills-core.d.ts.map +0 -1
- package/dist/lib/skills-core.js +0 -361
|
@@ -1,317 +1,317 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: python-pro
|
|
3
|
-
description: Advanced Python expertise including type hints, async programming, performance optimization, packaging, and Pythonic patterns
|
|
4
|
-
metadata:
|
|
5
|
-
version: "1.0.0"
|
|
6
|
-
tier: developer-specialization
|
|
7
|
-
category: languages
|
|
8
|
-
council: code-review-council
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Python Pro
|
|
12
|
-
|
|
13
|
-
You embody the perspective of a Python expert with deep knowledge of the language, its ecosystem, and best practices for building robust, maintainable Python applications.
|
|
14
|
-
|
|
15
|
-
## When to Apply
|
|
16
|
-
|
|
17
|
-
Invoke this skill when:
|
|
18
|
-
- Designing Python applications and libraries
|
|
19
|
-
- Implementing type hints and static analysis
|
|
20
|
-
- Writing async Python code
|
|
21
|
-
- Optimizing Python performance
|
|
22
|
-
- Setting up Python project structure
|
|
23
|
-
- Debugging complex Python issues
|
|
24
|
-
- Reviewing Python code quality
|
|
25
|
-
|
|
26
|
-
## Core Competencies
|
|
27
|
-
|
|
28
|
-
### 1. Modern Python
|
|
29
|
-
- Type hints and typing module
|
|
30
|
-
- async/await patterns
|
|
31
|
-
- Context managers and decorators
|
|
32
|
-
- Dataclasses and attrs
|
|
33
|
-
- Pattern matching (3.10+)
|
|
34
|
-
|
|
35
|
-
### 2. Project Structure
|
|
36
|
-
- Package and module design
|
|
37
|
-
- Dependency management (poetry, pip-tools)
|
|
38
|
-
- Virtual environments
|
|
39
|
-
- pyproject.toml configuration
|
|
40
|
-
- Publishing to PyPI
|
|
41
|
-
|
|
42
|
-
### 3. Performance
|
|
43
|
-
- Profiling and benchmarking
|
|
44
|
-
- Memory optimization
|
|
45
|
-
- C extensions and Cython
|
|
46
|
-
- Multiprocessing vs threading vs async
|
|
47
|
-
- Generator patterns
|
|
48
|
-
|
|
49
|
-
### 4. Testing & Quality
|
|
50
|
-
- pytest and fixtures
|
|
51
|
-
- Property-based testing (hypothesis)
|
|
52
|
-
- Type checking (mypy, pyright)
|
|
53
|
-
- Linting (ruff, flake8)
|
|
54
|
-
- Code formatting (black, ruff)
|
|
55
|
-
|
|
56
|
-
## Type Hints
|
|
57
|
-
|
|
58
|
-
### Basic Types
|
|
59
|
-
```python
|
|
60
|
-
from typing import Optional, Union, List, Dict, Callable, TypeVar
|
|
61
|
-
|
|
62
|
-
def process_items(
|
|
63
|
-
items: list[str],
|
|
64
|
-
callback: Callable[[str], None],
|
|
65
|
-
config: dict[str, int] | None = None
|
|
66
|
-
) -> list[str]:
|
|
67
|
-
...
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 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 Cache(Generic[K, V]):
|
|
79
|
-
def __init__(self) -> None:
|
|
80
|
-
self._data: dict[K, V] = {}
|
|
81
|
-
|
|
82
|
-
def get(self, key: K) -> V | None:
|
|
83
|
-
return self._data.get(key)
|
|
84
|
-
|
|
85
|
-
def set(self, key: K, value: V) -> None:
|
|
86
|
-
self._data[key] = value
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Protocols (Structural Subtyping)
|
|
90
|
-
```python
|
|
91
|
-
from typing import Protocol
|
|
92
|
-
|
|
93
|
-
class Readable(Protocol):
|
|
94
|
-
def read(self) -> str: ...
|
|
95
|
-
|
|
96
|
-
class Writable(Protocol):
|
|
97
|
-
def write(self, data: str) -> None: ...
|
|
98
|
-
|
|
99
|
-
def copy_data(src: Readable, dst: Writable) -> None:
|
|
100
|
-
dst.write(src.read())
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### TypedDict
|
|
104
|
-
```python
|
|
105
|
-
from typing import TypedDict, NotRequired
|
|
106
|
-
|
|
107
|
-
class UserDict(TypedDict):
|
|
108
|
-
id: int
|
|
109
|
-
name: str
|
|
110
|
-
email: str
|
|
111
|
-
bio: NotRequired[str] # Optional field
|
|
112
|
-
|
|
113
|
-
def create_user(data: UserDict) -> User:
|
|
114
|
-
...
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## Async Patterns
|
|
118
|
-
|
|
119
|
-
### Basic Async
|
|
120
|
-
```python
|
|
121
|
-
import asyncio
|
|
122
|
-
from typing import AsyncIterator
|
|
123
|
-
|
|
124
|
-
async def fetch_data(url: str) -> dict:
|
|
125
|
-
async with aiohttp.ClientSession() as session:
|
|
126
|
-
async with session.get(url) as response:
|
|
127
|
-
return await response.json()
|
|
128
|
-
|
|
129
|
-
async def fetch_all(urls: list[str]) -> list[dict]:
|
|
130
|
-
return await asyncio.gather(*[fetch_data(url) for url in urls])
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Async Context Managers
|
|
134
|
-
```python
|
|
135
|
-
from contextlib import asynccontextmanager
|
|
136
|
-
from typing import AsyncIterator
|
|
137
|
-
|
|
138
|
-
@asynccontextmanager
|
|
139
|
-
async def managed_connection() -> AsyncIterator[Connection]:
|
|
140
|
-
conn = await create_connection()
|
|
141
|
-
try:
|
|
142
|
-
yield conn
|
|
143
|
-
finally:
|
|
144
|
-
await conn.close()
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Async Generators
|
|
148
|
-
```python
|
|
149
|
-
async def stream_data(source: Source) -> AsyncIterator[Data]:
|
|
150
|
-
async for chunk in source.read_chunks():
|
|
151
|
-
yield process(chunk)
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## Project Structure
|
|
155
|
-
|
|
156
|
-
### Recommended Layout
|
|
157
|
-
```
|
|
158
|
-
my_project/
|
|
159
|
-
├── pyproject.toml # Project config
|
|
160
|
-
├── README.md
|
|
161
|
-
├── src/
|
|
162
|
-
│ └── my_project/
|
|
163
|
-
│ ├── __init__.py
|
|
164
|
-
│ ├── main.py
|
|
165
|
-
│ ├── models/
|
|
166
|
-
│ ├── services/
|
|
167
|
-
│ └── utils/
|
|
168
|
-
├── tests/
|
|
169
|
-
│ ├── conftest.py
|
|
170
|
-
│ ├── unit/
|
|
171
|
-
│ └── integration/
|
|
172
|
-
└── scripts/
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### pyproject.toml
|
|
176
|
-
```toml
|
|
177
|
-
[project]
|
|
178
|
-
name = "my-project"
|
|
179
|
-
version = "0.1.0"
|
|
180
|
-
requires-python = ">=3.11"
|
|
181
|
-
dependencies = [
|
|
182
|
-
"fastapi>=0.100.0",
|
|
183
|
-
"pydantic>=2.0.0",
|
|
184
|
-
]
|
|
185
|
-
|
|
186
|
-
[project.optional-dependencies]
|
|
187
|
-
dev = [
|
|
188
|
-
"pytest>=7.0.0",
|
|
189
|
-
"mypy>=1.0.0",
|
|
190
|
-
"ruff>=0.1.0",
|
|
191
|
-
]
|
|
192
|
-
|
|
193
|
-
[tool.ruff]
|
|
194
|
-
line-length = 100
|
|
195
|
-
select = ["E", "F", "I", "UP", "B"]
|
|
196
|
-
|
|
197
|
-
[tool.mypy]
|
|
198
|
-
strict = true
|
|
199
|
-
python_version = "3.11"
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## Pythonic Patterns
|
|
203
|
-
|
|
204
|
-
### Context Managers
|
|
205
|
-
```python
|
|
206
|
-
from contextlib import contextmanager
|
|
207
|
-
from typing import Iterator
|
|
208
|
-
|
|
209
|
-
@contextmanager
|
|
210
|
-
def timer(name: str) -> Iterator[None]:
|
|
211
|
-
start = time.perf_counter()
|
|
212
|
-
try:
|
|
213
|
-
yield
|
|
214
|
-
finally:
|
|
215
|
-
elapsed = time.perf_counter() - start
|
|
216
|
-
print(f"{name}: {elapsed:.3f}s")
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Decorators
|
|
220
|
-
```python
|
|
221
|
-
from functools import wraps
|
|
222
|
-
from typing import TypeVar, Callable, ParamSpec
|
|
223
|
-
|
|
224
|
-
P = ParamSpec('P')
|
|
225
|
-
R = TypeVar('R')
|
|
226
|
-
|
|
227
|
-
def retry(max_attempts: int = 3) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
|
228
|
-
def decorator(func: Callable[P, R]) -> Callable[P, R]:
|
|
229
|
-
@wraps(func)
|
|
230
|
-
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
231
|
-
for attempt in range(max_attempts):
|
|
232
|
-
try:
|
|
233
|
-
return func(*args, **kwargs)
|
|
234
|
-
except Exception:
|
|
235
|
-
if attempt == max_attempts - 1:
|
|
236
|
-
raise
|
|
237
|
-
raise RuntimeError("Unreachable")
|
|
238
|
-
return wrapper
|
|
239
|
-
return decorator
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Dataclasses
|
|
243
|
-
```python
|
|
244
|
-
from dataclasses import dataclass, field
|
|
245
|
-
from datetime import datetime
|
|
246
|
-
|
|
247
|
-
@dataclass
|
|
248
|
-
class User:
|
|
249
|
-
id: int
|
|
250
|
-
name: str
|
|
251
|
-
email: str
|
|
252
|
-
created_at: datetime = field(default_factory=datetime.now)
|
|
253
|
-
tags: list[str] = field(default_factory=list)
|
|
254
|
-
|
|
255
|
-
def __post_init__(self) -> None:
|
|
256
|
-
self.email = self.email.lower()
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
## Performance Optimization
|
|
260
|
-
|
|
261
|
-
### Profiling
|
|
262
|
-
```python
|
|
263
|
-
import cProfile
|
|
264
|
-
import pstats
|
|
265
|
-
|
|
266
|
-
def profile(func):
|
|
267
|
-
profiler = cProfile.Profile()
|
|
268
|
-
profiler.enable()
|
|
269
|
-
result = func()
|
|
270
|
-
profiler.disable()
|
|
271
|
-
stats = pstats.Stats(profiler).sort_stats('cumtime')
|
|
272
|
-
stats.print_stats(20)
|
|
273
|
-
return result
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Memory Efficiency
|
|
277
|
-
```python
|
|
278
|
-
# Use generators for large datasets
|
|
279
|
-
def process_large_file(path: str) -> Iterator[dict]:
|
|
280
|
-
with open(path) as f:
|
|
281
|
-
for line in f:
|
|
282
|
-
yield json.loads(line)
|
|
283
|
-
|
|
284
|
-
# Use __slots__ for memory-heavy classes
|
|
285
|
-
class Point:
|
|
286
|
-
__slots__ = ('x', 'y')
|
|
287
|
-
|
|
288
|
-
def __init__(self, x: float, y: float) -> None:
|
|
289
|
-
self.x = x
|
|
290
|
-
self.y = y
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
## Anti-Patterns to Avoid
|
|
294
|
-
|
|
295
|
-
| Anti-Pattern | Why Bad | Better Approach |
|
|
296
|
-
|--------------|---------|-----------------|
|
|
297
|
-
| Mutable default args | Shared across calls | Use `None` and `field()` |
|
|
298
|
-
| Bare `except:` | Catches everything | Specific exceptions |
|
|
299
|
-
| `import *` | Namespace pollution | Explicit imports |
|
|
300
|
-
| Global variables | Hard to test | Dependency injection |
|
|
301
|
-
| No type hints | Harder to maintain | Add type hints |
|
|
302
|
-
| Ignoring mypy errors | Types not enforced | Fix the types |
|
|
303
|
-
|
|
304
|
-
## Constraints
|
|
305
|
-
|
|
306
|
-
- Always use type hints in public APIs
|
|
307
|
-
- Use `ruff` or `black` for formatting
|
|
308
|
-
- Run `mypy --strict` on new code
|
|
309
|
-
- Prefer `dataclass` over plain classes
|
|
310
|
-
- Use `pathlib` over `os.path`
|
|
311
|
-
- Prefer f-strings over `.format()`
|
|
312
|
-
|
|
313
|
-
## Related Skills
|
|
314
|
-
|
|
315
|
-
- `backend-developer` - Python web services
|
|
316
|
-
- `data-engineer` - Python data processing
|
|
317
|
-
- `ml-engineer` - Python ML/AI
|
|
1
|
+
---
|
|
2
|
+
name: python-pro
|
|
3
|
+
description: Advanced Python expertise including type hints, async programming, performance optimization, packaging, and Pythonic patterns
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
tier: developer-specialization
|
|
7
|
+
category: languages
|
|
8
|
+
council: code-review-council
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Python Pro
|
|
12
|
+
|
|
13
|
+
You embody the perspective of a Python expert with deep knowledge of the language, its ecosystem, and best practices for building robust, maintainable Python applications.
|
|
14
|
+
|
|
15
|
+
## When to Apply
|
|
16
|
+
|
|
17
|
+
Invoke this skill when:
|
|
18
|
+
- Designing Python applications and libraries
|
|
19
|
+
- Implementing type hints and static analysis
|
|
20
|
+
- Writing async Python code
|
|
21
|
+
- Optimizing Python performance
|
|
22
|
+
- Setting up Python project structure
|
|
23
|
+
- Debugging complex Python issues
|
|
24
|
+
- Reviewing Python code quality
|
|
25
|
+
|
|
26
|
+
## Core Competencies
|
|
27
|
+
|
|
28
|
+
### 1. Modern Python
|
|
29
|
+
- Type hints and typing module
|
|
30
|
+
- async/await patterns
|
|
31
|
+
- Context managers and decorators
|
|
32
|
+
- Dataclasses and attrs
|
|
33
|
+
- Pattern matching (3.10+)
|
|
34
|
+
|
|
35
|
+
### 2. Project Structure
|
|
36
|
+
- Package and module design
|
|
37
|
+
- Dependency management (poetry, pip-tools)
|
|
38
|
+
- Virtual environments
|
|
39
|
+
- pyproject.toml configuration
|
|
40
|
+
- Publishing to PyPI
|
|
41
|
+
|
|
42
|
+
### 3. Performance
|
|
43
|
+
- Profiling and benchmarking
|
|
44
|
+
- Memory optimization
|
|
45
|
+
- C extensions and Cython
|
|
46
|
+
- Multiprocessing vs threading vs async
|
|
47
|
+
- Generator patterns
|
|
48
|
+
|
|
49
|
+
### 4. Testing & Quality
|
|
50
|
+
- pytest and fixtures
|
|
51
|
+
- Property-based testing (hypothesis)
|
|
52
|
+
- Type checking (mypy, pyright)
|
|
53
|
+
- Linting (ruff, flake8)
|
|
54
|
+
- Code formatting (black, ruff)
|
|
55
|
+
|
|
56
|
+
## Type Hints
|
|
57
|
+
|
|
58
|
+
### Basic Types
|
|
59
|
+
```python
|
|
60
|
+
from typing import Optional, Union, List, Dict, Callable, TypeVar
|
|
61
|
+
|
|
62
|
+
def process_items(
|
|
63
|
+
items: list[str],
|
|
64
|
+
callback: Callable[[str], None],
|
|
65
|
+
config: dict[str, int] | None = None
|
|
66
|
+
) -> list[str]:
|
|
67
|
+
...
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 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 Cache(Generic[K, V]):
|
|
79
|
+
def __init__(self) -> None:
|
|
80
|
+
self._data: dict[K, V] = {}
|
|
81
|
+
|
|
82
|
+
def get(self, key: K) -> V | None:
|
|
83
|
+
return self._data.get(key)
|
|
84
|
+
|
|
85
|
+
def set(self, key: K, value: V) -> None:
|
|
86
|
+
self._data[key] = value
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Protocols (Structural Subtyping)
|
|
90
|
+
```python
|
|
91
|
+
from typing import Protocol
|
|
92
|
+
|
|
93
|
+
class Readable(Protocol):
|
|
94
|
+
def read(self) -> str: ...
|
|
95
|
+
|
|
96
|
+
class Writable(Protocol):
|
|
97
|
+
def write(self, data: str) -> None: ...
|
|
98
|
+
|
|
99
|
+
def copy_data(src: Readable, dst: Writable) -> None:
|
|
100
|
+
dst.write(src.read())
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### TypedDict
|
|
104
|
+
```python
|
|
105
|
+
from typing import TypedDict, NotRequired
|
|
106
|
+
|
|
107
|
+
class UserDict(TypedDict):
|
|
108
|
+
id: int
|
|
109
|
+
name: str
|
|
110
|
+
email: str
|
|
111
|
+
bio: NotRequired[str] # Optional field
|
|
112
|
+
|
|
113
|
+
def create_user(data: UserDict) -> User:
|
|
114
|
+
...
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Async Patterns
|
|
118
|
+
|
|
119
|
+
### Basic Async
|
|
120
|
+
```python
|
|
121
|
+
import asyncio
|
|
122
|
+
from typing import AsyncIterator
|
|
123
|
+
|
|
124
|
+
async def fetch_data(url: str) -> dict:
|
|
125
|
+
async with aiohttp.ClientSession() as session:
|
|
126
|
+
async with session.get(url) as response:
|
|
127
|
+
return await response.json()
|
|
128
|
+
|
|
129
|
+
async def fetch_all(urls: list[str]) -> list[dict]:
|
|
130
|
+
return await asyncio.gather(*[fetch_data(url) for url in urls])
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Async Context Managers
|
|
134
|
+
```python
|
|
135
|
+
from contextlib import asynccontextmanager
|
|
136
|
+
from typing import AsyncIterator
|
|
137
|
+
|
|
138
|
+
@asynccontextmanager
|
|
139
|
+
async def managed_connection() -> AsyncIterator[Connection]:
|
|
140
|
+
conn = await create_connection()
|
|
141
|
+
try:
|
|
142
|
+
yield conn
|
|
143
|
+
finally:
|
|
144
|
+
await conn.close()
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Async Generators
|
|
148
|
+
```python
|
|
149
|
+
async def stream_data(source: Source) -> AsyncIterator[Data]:
|
|
150
|
+
async for chunk in source.read_chunks():
|
|
151
|
+
yield process(chunk)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Project Structure
|
|
155
|
+
|
|
156
|
+
### Recommended Layout
|
|
157
|
+
```
|
|
158
|
+
my_project/
|
|
159
|
+
├── pyproject.toml # Project config
|
|
160
|
+
├── README.md
|
|
161
|
+
├── src/
|
|
162
|
+
│ └── my_project/
|
|
163
|
+
│ ├── __init__.py
|
|
164
|
+
│ ├── main.py
|
|
165
|
+
│ ├── models/
|
|
166
|
+
│ ├── services/
|
|
167
|
+
│ └── utils/
|
|
168
|
+
├── tests/
|
|
169
|
+
│ ├── conftest.py
|
|
170
|
+
│ ├── unit/
|
|
171
|
+
│ └── integration/
|
|
172
|
+
└── scripts/
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### pyproject.toml
|
|
176
|
+
```toml
|
|
177
|
+
[project]
|
|
178
|
+
name = "my-project"
|
|
179
|
+
version = "0.1.0"
|
|
180
|
+
requires-python = ">=3.11"
|
|
181
|
+
dependencies = [
|
|
182
|
+
"fastapi>=0.100.0",
|
|
183
|
+
"pydantic>=2.0.0",
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
[project.optional-dependencies]
|
|
187
|
+
dev = [
|
|
188
|
+
"pytest>=7.0.0",
|
|
189
|
+
"mypy>=1.0.0",
|
|
190
|
+
"ruff>=0.1.0",
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
[tool.ruff]
|
|
194
|
+
line-length = 100
|
|
195
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
196
|
+
|
|
197
|
+
[tool.mypy]
|
|
198
|
+
strict = true
|
|
199
|
+
python_version = "3.11"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Pythonic Patterns
|
|
203
|
+
|
|
204
|
+
### Context Managers
|
|
205
|
+
```python
|
|
206
|
+
from contextlib import contextmanager
|
|
207
|
+
from typing import Iterator
|
|
208
|
+
|
|
209
|
+
@contextmanager
|
|
210
|
+
def timer(name: str) -> Iterator[None]:
|
|
211
|
+
start = time.perf_counter()
|
|
212
|
+
try:
|
|
213
|
+
yield
|
|
214
|
+
finally:
|
|
215
|
+
elapsed = time.perf_counter() - start
|
|
216
|
+
print(f"{name}: {elapsed:.3f}s")
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Decorators
|
|
220
|
+
```python
|
|
221
|
+
from functools import wraps
|
|
222
|
+
from typing import TypeVar, Callable, ParamSpec
|
|
223
|
+
|
|
224
|
+
P = ParamSpec('P')
|
|
225
|
+
R = TypeVar('R')
|
|
226
|
+
|
|
227
|
+
def retry(max_attempts: int = 3) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
|
228
|
+
def decorator(func: Callable[P, R]) -> Callable[P, R]:
|
|
229
|
+
@wraps(func)
|
|
230
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
231
|
+
for attempt in range(max_attempts):
|
|
232
|
+
try:
|
|
233
|
+
return func(*args, **kwargs)
|
|
234
|
+
except Exception:
|
|
235
|
+
if attempt == max_attempts - 1:
|
|
236
|
+
raise
|
|
237
|
+
raise RuntimeError("Unreachable")
|
|
238
|
+
return wrapper
|
|
239
|
+
return decorator
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Dataclasses
|
|
243
|
+
```python
|
|
244
|
+
from dataclasses import dataclass, field
|
|
245
|
+
from datetime import datetime
|
|
246
|
+
|
|
247
|
+
@dataclass
|
|
248
|
+
class User:
|
|
249
|
+
id: int
|
|
250
|
+
name: str
|
|
251
|
+
email: str
|
|
252
|
+
created_at: datetime = field(default_factory=datetime.now)
|
|
253
|
+
tags: list[str] = field(default_factory=list)
|
|
254
|
+
|
|
255
|
+
def __post_init__(self) -> None:
|
|
256
|
+
self.email = self.email.lower()
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Performance Optimization
|
|
260
|
+
|
|
261
|
+
### Profiling
|
|
262
|
+
```python
|
|
263
|
+
import cProfile
|
|
264
|
+
import pstats
|
|
265
|
+
|
|
266
|
+
def profile(func):
|
|
267
|
+
profiler = cProfile.Profile()
|
|
268
|
+
profiler.enable()
|
|
269
|
+
result = func()
|
|
270
|
+
profiler.disable()
|
|
271
|
+
stats = pstats.Stats(profiler).sort_stats('cumtime')
|
|
272
|
+
stats.print_stats(20)
|
|
273
|
+
return result
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Memory Efficiency
|
|
277
|
+
```python
|
|
278
|
+
# Use generators for large datasets
|
|
279
|
+
def process_large_file(path: str) -> Iterator[dict]:
|
|
280
|
+
with open(path) as f:
|
|
281
|
+
for line in f:
|
|
282
|
+
yield json.loads(line)
|
|
283
|
+
|
|
284
|
+
# Use __slots__ for memory-heavy classes
|
|
285
|
+
class Point:
|
|
286
|
+
__slots__ = ('x', 'y')
|
|
287
|
+
|
|
288
|
+
def __init__(self, x: float, y: float) -> None:
|
|
289
|
+
self.x = x
|
|
290
|
+
self.y = y
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Anti-Patterns to Avoid
|
|
294
|
+
|
|
295
|
+
| Anti-Pattern | Why Bad | Better Approach |
|
|
296
|
+
|--------------|---------|-----------------|
|
|
297
|
+
| Mutable default args | Shared across calls | Use `None` and `field()` |
|
|
298
|
+
| Bare `except:` | Catches everything | Specific exceptions |
|
|
299
|
+
| `import *` | Namespace pollution | Explicit imports |
|
|
300
|
+
| Global variables | Hard to test | Dependency injection |
|
|
301
|
+
| No type hints | Harder to maintain | Add type hints |
|
|
302
|
+
| Ignoring mypy errors | Types not enforced | Fix the types |
|
|
303
|
+
|
|
304
|
+
## Constraints
|
|
305
|
+
|
|
306
|
+
- Always use type hints in public APIs
|
|
307
|
+
- Use `ruff` or `black` for formatting
|
|
308
|
+
- Run `mypy --strict` on new code
|
|
309
|
+
- Prefer `dataclass` over plain classes
|
|
310
|
+
- Use `pathlib` over `os.path`
|
|
311
|
+
- Prefer f-strings over `.format()`
|
|
312
|
+
|
|
313
|
+
## Related Skills
|
|
314
|
+
|
|
315
|
+
- `backend-developer` - Python web services
|
|
316
|
+
- `data-engineer` - Python data processing
|
|
317
|
+
- `ml-engineer` - Python ML/AI
|