agentic-team-templates 0.12.0 → 0.13.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.
@@ -0,0 +1,264 @@
1
+ # Python Expert Development Guide
2
+
3
+ Principal-level guidelines for Python engineering. Idiomatic Python, production systems, and deep interpreter knowledge.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ This guide applies to:
10
+ - Web services and APIs (Django, FastAPI, Flask)
11
+ - CLI tools and automation
12
+ - Data processing and ETL pipelines
13
+ - Libraries and PyPI packages
14
+ - Async services and event-driven architectures
15
+
16
+ ### Core Philosophy
17
+
18
+ Python's power is in its clarity. The best Python code reads like well-written prose.
19
+
20
+ - **Readability counts.** The Zen of Python is the engineering standard.
21
+ - **Explicit is better than implicit.** Type hints, clear names, no magic.
22
+ - **Errors should never pass silently.** Bare `except:` is a bug.
23
+ - **The standard library is rich — use it.** `collections`, `itertools`, `pathlib`, `dataclasses`, `contextlib`.
24
+ - **If you don't know, say so.** Admitting uncertainty is professional.
25
+
26
+ ### Project Structure
27
+
28
+ ```
29
+ project/
30
+ ├── src/mypackage/
31
+ │ ├── __init__.py
32
+ │ ├── py.typed
33
+ │ ├── models/
34
+ │ ├── services/
35
+ │ ├── repositories/
36
+ │ └── api/
37
+ ├── tests/
38
+ │ ├── conftest.py
39
+ │ ├── unit/
40
+ │ └── integration/
41
+ ├── pyproject.toml
42
+ └── Makefile
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Type System
48
+
49
+ ### Modern Typed Python
50
+
51
+ ```python
52
+ def fetch_users(
53
+ db: Database, *, limit: int = 100, active_only: bool = True
54
+ ) -> list[User]: ...
55
+
56
+ # Union types (3.10+)
57
+ def find_user(email: str) -> User | None: ...
58
+
59
+ # Protocol for structural subtyping
60
+ class Renderable(Protocol):
61
+ def render(self) -> str: ...
62
+ ```
63
+
64
+ ### Rules
65
+
66
+ - `mypy --strict` is the baseline
67
+ - All function signatures fully typed
68
+ - `dataclasses` or Pydantic over raw dicts
69
+ - No `Any` as a crutch — type properly or explain why not
70
+ - No `# type: ignore` without inline explanation
71
+
72
+ ---
73
+
74
+ ## Patterns and Idioms
75
+
76
+ ### Data Model
77
+
78
+ Implement `__repr__`, `__eq__`, `__hash__` via `@dataclass`. Use `frozen=True` and `slots=True` for immutable value objects.
79
+
80
+ ### Generators
81
+
82
+ ```python
83
+ def read_large_file(path: Path) -> Iterator[str]:
84
+ with open(path) as f:
85
+ for line in f:
86
+ yield line.strip()
87
+
88
+ # Generator expressions over list comprehensions when iterating once
89
+ total = sum(order.total for order in orders)
90
+ ```
91
+
92
+ ### Context Managers
93
+
94
+ ```python
95
+ @contextmanager
96
+ def timed_operation(name: str) -> Iterator[None]:
97
+ start = time.monotonic()
98
+ try:
99
+ yield
100
+ finally:
101
+ logger.info(f"{name} took {time.monotonic() - start:.3f}s")
102
+ ```
103
+
104
+ ### Decorators
105
+
106
+ Use `functools.wraps` and `ParamSpec` for properly typed decorators that preserve signatures.
107
+
108
+ ---
109
+
110
+ ## Async Python
111
+
112
+ ### TaskGroup (3.11+)
113
+
114
+ ```python
115
+ async with asyncio.TaskGroup() as tg:
116
+ user_task = tg.create_task(fetch_users())
117
+ post_task = tg.create_task(fetch_posts())
118
+ # All complete or all cancelled on failure
119
+ ```
120
+
121
+ ### Bounded Concurrency
122
+
123
+ ```python
124
+ semaphore = asyncio.Semaphore(10)
125
+ async def bounded_fetch(url: str) -> Response:
126
+ async with semaphore:
127
+ return await fetch(url)
128
+ ```
129
+
130
+ ### Rules
131
+
132
+ - Never use blocking calls (`requests`, `time.sleep`) in async code
133
+ - Use `run_in_executor` for CPU-bound work
134
+ - Every spawned task needs error handling
135
+ - Use `asyncio.timeout()` (3.11+) for deadlines
136
+
137
+ ---
138
+
139
+ ## Testing
140
+
141
+ ### pytest Patterns
142
+
143
+ ```python
144
+ @pytest.mark.parametrize("input_str, expected", [
145
+ ("hello world", "hello-world"),
146
+ ("UPPER", "upper"),
147
+ ("", ""),
148
+ ])
149
+ def test_slugify(input_str: str, expected: str) -> None:
150
+ assert slugify(input_str) == expected
151
+ ```
152
+
153
+ ### Dependency Injection Over Mocking
154
+
155
+ ```python
156
+ def test_create_user_sends_notification() -> None:
157
+ notifier = Mock(spec=Notifier)
158
+ service = UserService(FakeUserRepo(), notifier)
159
+ service.create(input_data)
160
+ notifier.send_welcome.assert_called_once()
161
+ ```
162
+
163
+ ### Rules
164
+
165
+ - Arrange-Act-Assert structure
166
+ - Descriptive test names
167
+ - Test error cases, not just happy paths
168
+ - Prefer DI over `@patch`
169
+ - No `time.sleep()` in tests
170
+
171
+ ---
172
+
173
+ ## Performance
174
+
175
+ ### Profile First
176
+
177
+ ```bash
178
+ py-spy record -o profile.svg -- python myapp.py
179
+ ```
180
+
181
+ ### Key Patterns
182
+
183
+ - `"".join()` over `+=` for string concatenation
184
+ - Generator expressions to avoid intermediate lists
185
+ - `set` for O(1) membership testing
186
+ - `deque` for O(1) append/pop from both ends
187
+ - `slots=True` on dataclasses for memory efficiency
188
+ - `ThreadPoolExecutor` for I/O parallelism
189
+ - `ProcessPoolExecutor` for CPU parallelism
190
+ - `lru_cache` / `cache` for expensive pure functions
191
+
192
+ ---
193
+
194
+ ## Web and APIs
195
+
196
+ ### FastAPI
197
+
198
+ ```python
199
+ CurrentUser = Annotated[User, Depends(get_current_user)]
200
+ DB = Annotated[Database, Depends(get_db)]
201
+
202
+ @app.get("/users/me")
203
+ async def get_me(user: CurrentUser) -> UserResponse:
204
+ return UserResponse.model_validate(user)
205
+ ```
206
+
207
+ ### Pydantic for Validation
208
+
209
+ ```python
210
+ class CreateUserRequest(BaseModel):
211
+ model_config = ConfigDict(strict=True)
212
+ name: str = Field(min_length=1, max_length=200)
213
+ email: EmailStr
214
+ ```
215
+
216
+ ### Configuration
217
+
218
+ ```python
219
+ class Settings(BaseSettings):
220
+ model_config = ConfigDict(env_file=".env")
221
+ database_url: str
222
+ debug: bool = False
223
+ settings = Settings() # Validate at import time
224
+ ```
225
+
226
+ ---
227
+
228
+ ## Tooling
229
+
230
+ ### Essential Stack
231
+
232
+ | Tool | Purpose |
233
+ |------|---------|
234
+ | uv | Package management |
235
+ | ruff | Linting + formatting |
236
+ | mypy | Type checking |
237
+ | pytest | Testing |
238
+ | pre-commit | Git hooks |
239
+
240
+ ### CI Essentials
241
+
242
+ ```bash
243
+ ruff format --check .
244
+ ruff check .
245
+ mypy .
246
+ pytest --cov
247
+ pip-audit .
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Definition of Done
253
+
254
+ A Python feature is complete when:
255
+
256
+ - [ ] `mypy --strict` passes
257
+ - [ ] `ruff check` and `ruff format --check` pass
258
+ - [ ] `pytest` passes with no failures
259
+ - [ ] Error cases are tested
260
+ - [ ] Docstrings on all public functions and classes
261
+ - [ ] No bare `except:` without re-raise
262
+ - [ ] No mutable default arguments
263
+ - [ ] No `# type: ignore` without explanation
264
+ - [ ] Code reviewed and approved