ma-agents 3.2.0 → 3.3.0
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/.opencode/skills/.ma-agents.json +99 -99
- package/.roo/rules/00-ma-agents.md +13 -0
- package/.roo/skills/.ma-agents.json +241 -0
- package/.roo/skills/MANIFEST.yaml +254 -0
- package/.roo/skills/ai-audit-trail/SKILL.md +23 -0
- package/.roo/skills/auto-bug-detection/SKILL.md +169 -0
- package/.roo/skills/cmake-best-practices/SKILL.md +64 -0
- package/.roo/skills/cmake-best-practices/examples/cmake.md +59 -0
- package/.roo/skills/code-documentation/SKILL.md +57 -0
- package/.roo/skills/code-documentation/examples/cpp.md +29 -0
- package/.roo/skills/code-documentation/examples/csharp.md +28 -0
- package/.roo/skills/code-documentation/examples/javascript_typescript.md +28 -0
- package/.roo/skills/code-documentation/examples/python.md +57 -0
- package/.roo/skills/code-review/SKILL.md +43 -0
- package/.roo/skills/commit-message/SKILL.md +79 -0
- package/.roo/skills/cpp-best-practices/SKILL.md +234 -0
- package/.roo/skills/cpp-best-practices/examples/modern-idioms.md +189 -0
- package/.roo/skills/cpp-best-practices/examples/naming-and-organization.md +102 -0
- package/.roo/skills/cpp-concurrency-safety/SKILL.md +60 -0
- package/.roo/skills/cpp-concurrency-safety/examples/concurrency.md +73 -0
- package/.roo/skills/cpp-const-correctness/SKILL.md +63 -0
- package/.roo/skills/cpp-const-correctness/examples/const_correctness.md +54 -0
- package/.roo/skills/cpp-memory-handling/SKILL.md +42 -0
- package/.roo/skills/cpp-memory-handling/examples/modern-cpp.md +49 -0
- package/.roo/skills/cpp-memory-handling/examples/smart-pointers.md +46 -0
- package/.roo/skills/cpp-modern-composition/SKILL.md +64 -0
- package/.roo/skills/cpp-modern-composition/examples/composition.md +51 -0
- package/.roo/skills/cpp-robust-interfaces/SKILL.md +55 -0
- package/.roo/skills/cpp-robust-interfaces/examples/interfaces.md +56 -0
- package/.roo/skills/create-hardened-docker-skill/SKILL.md +637 -0
- package/.roo/skills/create-hardened-docker-skill/scripts/create-all.sh +489 -0
- package/.roo/skills/csharp-best-practices/SKILL.md +278 -0
- package/.roo/skills/docker-hardening-verification/SKILL.md +28 -0
- package/.roo/skills/docker-hardening-verification/scripts/verify-hardening.sh +39 -0
- package/.roo/skills/docker-image-signing/SKILL.md +28 -0
- package/.roo/skills/docker-image-signing/scripts/sign-image.sh +33 -0
- package/.roo/skills/document-revision-history/SKILL.md +104 -0
- package/.roo/skills/git-workflow-skill/SKILL.md +194 -0
- package/.roo/skills/git-workflow-skill/hooks/commit-msg +61 -0
- package/.roo/skills/git-workflow-skill/hooks/pre-commit +38 -0
- package/.roo/skills/git-workflow-skill/hooks/prepare-commit-msg +56 -0
- package/.roo/skills/git-workflow-skill/scripts/finish-feature.sh +192 -0
- package/.roo/skills/git-workflow-skill/scripts/install-hooks.sh +55 -0
- package/.roo/skills/git-workflow-skill/scripts/start-feature.sh +110 -0
- package/.roo/skills/git-workflow-skill/scripts/validate-workflow.sh +229 -0
- package/.roo/skills/js-ts-dependency-mgmt/SKILL.md +49 -0
- package/.roo/skills/js-ts-dependency-mgmt/examples/dependency_mgmt.md +60 -0
- package/.roo/skills/js-ts-security-skill/SKILL.md +64 -0
- package/.roo/skills/js-ts-security-skill/scripts/verify-security.sh +136 -0
- package/.roo/skills/logging-best-practices/SKILL.md +50 -0
- package/.roo/skills/logging-best-practices/examples/cpp.md +36 -0
- package/.roo/skills/logging-best-practices/examples/csharp.md +49 -0
- package/.roo/skills/logging-best-practices/examples/javascript.md +77 -0
- package/.roo/skills/logging-best-practices/examples/python.md +57 -0
- package/.roo/skills/logging-best-practices/references/logging-standards.md +29 -0
- package/.roo/skills/open-presentation/SKILL.md +35 -0
- package/.roo/skills/opentelemetry-best-practices/SKILL.md +34 -0
- package/.roo/skills/opentelemetry-best-practices/examples/go.md +32 -0
- package/.roo/skills/opentelemetry-best-practices/examples/javascript.md +58 -0
- package/.roo/skills/opentelemetry-best-practices/examples/python.md +37 -0
- package/.roo/skills/opentelemetry-best-practices/references/otel-standards.md +37 -0
- package/.roo/skills/python-best-practices/SKILL.md +385 -0
- package/.roo/skills/python-dependency-mgmt/SKILL.md +42 -0
- package/.roo/skills/python-dependency-mgmt/examples/dependency_mgmt.md +67 -0
- package/.roo/skills/python-security-skill/SKILL.md +56 -0
- package/.roo/skills/python-security-skill/examples/security.md +56 -0
- package/.roo/skills/self-signed-cert/SKILL.md +42 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.ps1 +45 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.sh +43 -0
- package/.roo/skills/skill-creator/SKILL.md +196 -0
- package/.roo/skills/skill-creator/references/output-patterns.md +82 -0
- package/.roo/skills/skill-creator/references/workflows.md +28 -0
- package/.roo/skills/skill-creator/scripts/init_skill.py +208 -0
- package/.roo/skills/skill-creator/scripts/package_skill.py +99 -0
- package/.roo/skills/skill-creator/scripts/quick_validate.py +113 -0
- package/.roo/skills/story-status-lookup/SKILL.md +78 -0
- package/.roo/skills/test-accompanied-development/SKILL.md +50 -0
- package/.roo/skills/test-generator/SKILL.md +65 -0
- package/.roo/skills/vercel-react-best-practices/SKILL.md +109 -0
- package/.roo/skills/verify-hardened-docker-skill/SKILL.md +442 -0
- package/.roo/skills/verify-hardened-docker-skill/scripts/verify-docker-hardening.sh +439 -0
- package/README.md +2 -1
- package/lib/agents.js +23 -0
- package/package.json +4 -3
- package/test/roo-code-agent.test.js +166 -0
- package/test/roo-code-injection.test.js +172 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Python Best Practices
|
|
3
|
+
description: Comprehensive Python coding standards covering PEP 8 conventions, type hinting (3.10+), modern patterns (match/case, exception groups), async, and packaging best practices. Cross-references security-focused Python skills.
|
|
4
|
+
---
|
|
5
|
+
# Python Best Practices
|
|
6
|
+
|
|
7
|
+
Coding standards for modern Python (3.10+). This skill covers language-level patterns, type hinting, async conventions, and packaging. For security and dependency hardening, see the cross-referenced skills at the end of this document.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Naming Conventions (PEP 8)
|
|
12
|
+
|
|
13
|
+
**Rule:** Use consistent naming to maximize readability and tooling compatibility.
|
|
14
|
+
|
|
15
|
+
| Element | Convention | Example |
|
|
16
|
+
|---------|-----------|---------|
|
|
17
|
+
| Module / package | `snake_case` | `order_service`, `user_auth` |
|
|
18
|
+
| Function / method | `snake_case` | `get_customer()`, `parse_response()` |
|
|
19
|
+
| Variable | `snake_case` | `customer_count`, `is_active` |
|
|
20
|
+
| Class | `PascalCase` | `CustomerService`, `OrderItem` |
|
|
21
|
+
| Exception | `PascalCase` + `Error`/`Exception` | `NotFoundError`, `ValidationException` |
|
|
22
|
+
| Constant | `UPPER_SNAKE_CASE` | `MAX_RETRY_COUNT`, `DEFAULT_TIMEOUT` |
|
|
23
|
+
| Type alias | `PascalCase` | `CustomerList`, `JsonPayload` |
|
|
24
|
+
| Private identifier | leading `_` | `_internal_helper()`, `_cache` |
|
|
25
|
+
| Dunder / magic | leading and trailing `__` | `__init__`, `__repr__` |
|
|
26
|
+
|
|
27
|
+
- Do not abbreviate names unless the abbreviation is universally understood in the domain (`url`, `id`, `db`).
|
|
28
|
+
- Avoid single-letter names except for short-lived loop indices (`i`, `j`) or mathematical variables.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 2. Code Organization
|
|
33
|
+
|
|
34
|
+
**Rule:** Keep modules focused; make boundaries explicit via `__all__`.
|
|
35
|
+
|
|
36
|
+
- One logical concept per module; group related modules into packages with `__init__.py`.
|
|
37
|
+
- Declare `__all__` in any module intended for public consumption to control the exported API.
|
|
38
|
+
- Standard import order (enforced by `ruff`): stdlib → third-party → local. One blank line between each group.
|
|
39
|
+
- Use absolute imports; avoid relative imports except within a tightly coupled sub-package.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
# __init__.py — explicit public surface
|
|
43
|
+
from .service import CustomerService
|
|
44
|
+
from .models import Customer, Address
|
|
45
|
+
|
|
46
|
+
__all__ = ["CustomerService", "Customer", "Address"]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 3. Type Hinting (3.10+)
|
|
52
|
+
|
|
53
|
+
**Rule:** Annotate all public function signatures and module-level variables. Use modern syntax.
|
|
54
|
+
|
|
55
|
+
### 3.1 Modern Syntax Table
|
|
56
|
+
|
|
57
|
+
| Pattern | Pre-3.10 (avoid) | Modern 3.10+ (use) |
|
|
58
|
+
|---------|-----------------|-------------------|
|
|
59
|
+
| Union types | `Union[str, int]` | `str \| int` |
|
|
60
|
+
| Optional | `Optional[str]` | `str \| None` |
|
|
61
|
+
| List | `List[str]` | `list[str]` |
|
|
62
|
+
| Dict | `Dict[str, int]` | `dict[str, int]` |
|
|
63
|
+
| Tuple | `Tuple[str, ...]` | `tuple[str, ...]` |
|
|
64
|
+
| Set | `Set[int]` | `set[int]` |
|
|
65
|
+
| Type alias (3.12+) | `MyType = list[str]` | `type MyType = list[str]` |
|
|
66
|
+
| Callable | `Callable[[int], str]` | `Callable[[int], str]` (unchanged) |
|
|
67
|
+
|
|
68
|
+
### 3.2 Advanced Typing Constructs
|
|
69
|
+
|
|
70
|
+
- **`TypeAlias`** (3.10): use for readability when the alias is used in multiple places but you cannot yet use the `type` statement.
|
|
71
|
+
- **`TypeVar`**: constrain generic functions to a family of types.
|
|
72
|
+
- **`ParamSpec`** (3.10): preserve parameter types in higher-order functions and decorators.
|
|
73
|
+
- **`Protocol`**: define structural (duck-typed) interfaces; prefer over ABC for external or loosely coupled types.
|
|
74
|
+
- **`TypeGuard`** (3.10): narrow types in user-defined type guard functions.
|
|
75
|
+
- **`Self`** (3.11): annotate methods that return the instance's own type (replaces `TypeVar("T", bound="MyClass")`).
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from typing import TypeVar, ParamSpec, Protocol, TypeGuard
|
|
79
|
+
from typing import Self # 3.11+
|
|
80
|
+
|
|
81
|
+
T = TypeVar("T")
|
|
82
|
+
P = ParamSpec("P")
|
|
83
|
+
|
|
84
|
+
class Comparable(Protocol):
|
|
85
|
+
def __lt__(self, other: Self) -> bool: ...
|
|
86
|
+
|
|
87
|
+
def is_string_list(val: list[object]) -> TypeGuard[list[str]]:
|
|
88
|
+
return all(isinstance(x, str) for x in val)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 3.3 Variable Annotations
|
|
92
|
+
|
|
93
|
+
Annotate module-level and class-level variables; omit annotations for obvious local assignments.
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
# Module-level
|
|
97
|
+
MAX_CONNECTIONS: int = 100
|
|
98
|
+
_cache: dict[str, bytes] = {}
|
|
99
|
+
|
|
100
|
+
# Class-level (with __slots__ for memory efficiency)
|
|
101
|
+
class Point:
|
|
102
|
+
__slots__ = ("x", "y")
|
|
103
|
+
x: float
|
|
104
|
+
y: float
|
|
105
|
+
|
|
106
|
+
def __init__(self, x: float, y: float) -> None:
|
|
107
|
+
self.x = x
|
|
108
|
+
self.y = y
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 4. Modern Python Patterns
|
|
114
|
+
|
|
115
|
+
### 4.1 Structural Pattern Matching (3.10)
|
|
116
|
+
|
|
117
|
+
Use `match/case` to replace complex `if/elif` chains on structured data.
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
def handle_event(event: dict) -> str:
|
|
121
|
+
match event:
|
|
122
|
+
case {"type": "click", "button": button}:
|
|
123
|
+
return f"Clicked {button}"
|
|
124
|
+
case {"type": "keypress", "key": key} if key.isalpha():
|
|
125
|
+
return f"Key pressed: {key}"
|
|
126
|
+
case {"type": "resize", "width": w, "height": h}:
|
|
127
|
+
return f"Resized to {w}x{h}"
|
|
128
|
+
case _:
|
|
129
|
+
return "Unknown event"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Prefer `match/case` over `isinstance` chains when dispatching on data shape; avoid it for simple boolean conditions.
|
|
133
|
+
|
|
134
|
+
### 4.2 Exception Groups and `except*` (3.11)
|
|
135
|
+
|
|
136
|
+
`ExceptionGroup` allows multiple unrelated exceptions to propagate together; `except*` handles them selectively.
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
import asyncio
|
|
140
|
+
|
|
141
|
+
async def gather_tasks() -> None:
|
|
142
|
+
async with asyncio.TaskGroup() as tg:
|
|
143
|
+
tg.create_task(fetch_user())
|
|
144
|
+
tg.create_task(fetch_orders())
|
|
145
|
+
# TaskGroup raises ExceptionGroup if any task fails
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
await gather_tasks()
|
|
149
|
+
except* ValueError as eg:
|
|
150
|
+
for exc in eg.exceptions:
|
|
151
|
+
print(f"Validation error: {exc}")
|
|
152
|
+
except* IOError as eg:
|
|
153
|
+
for exc in eg.exceptions:
|
|
154
|
+
print(f"IO error: {exc}")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 4.3 F-String Improvements (3.12)
|
|
158
|
+
|
|
159
|
+
3.12 removes restrictions on f-string content: nested quotes, backslashes, and complex expressions are now valid.
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
# 3.12: nested quotes and backslashes inside f-strings
|
|
163
|
+
name = "world"
|
|
164
|
+
msg = f"Hello, {name!r}"
|
|
165
|
+
path = f"{'\\'.join(['a', 'b', 'c'])}" # backslash inside f-string (3.12+)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 4.4 Walrus Operator (`:=`)
|
|
169
|
+
|
|
170
|
+
Use assignment expressions to eliminate redundant calls in comprehensions and loops.
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
# With walrus — single call
|
|
174
|
+
if result := compute_expensive():
|
|
175
|
+
process(result)
|
|
176
|
+
|
|
177
|
+
# In comprehension — filter and use in one expression
|
|
178
|
+
filtered = [cleaned for raw in records if (cleaned := clean(raw))]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Use sparingly; prefer clarity over brevity when the expression becomes hard to read.
|
|
182
|
+
|
|
183
|
+
### 4.5 `__slots__` Usage
|
|
184
|
+
|
|
185
|
+
Declare `__slots__` on data-heavy classes to reduce per-instance memory by 30-50%.
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
class Vector:
|
|
189
|
+
__slots__ = ("x", "y", "z")
|
|
190
|
+
|
|
191
|
+
def __init__(self, x: float, y: float, z: float) -> None:
|
|
192
|
+
self.x, self.y, self.z = x, y, z
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Do not use `__slots__` on classes intended to be subclassed without explicit slot coordination.
|
|
196
|
+
|
|
197
|
+
### 4.6 Dataclasses vs attrs vs Pydantic
|
|
198
|
+
|
|
199
|
+
| Tool | When to use |
|
|
200
|
+
|------|-------------|
|
|
201
|
+
| `dataclasses` (stdlib) | Simple data containers; no validation; no serialization needed |
|
|
202
|
+
| `attrs` | More control than dataclasses; validators, converters, `__slots__` automation |
|
|
203
|
+
| `Pydantic v2` | External data (API requests, config files); runtime validation and JSON serialization |
|
|
204
|
+
|
|
205
|
+
- Use `@dataclass(frozen=True, slots=True)` for immutable value objects.
|
|
206
|
+
- Use Pydantic `BaseModel` at system boundaries (HTTP, config); avoid deep inside the domain layer.
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from dataclasses import dataclass
|
|
210
|
+
|
|
211
|
+
@dataclass(frozen=True, slots=True)
|
|
212
|
+
class Money:
|
|
213
|
+
amount: int # in cents
|
|
214
|
+
currency: str
|
|
215
|
+
|
|
216
|
+
def __post_init__(self) -> None:
|
|
217
|
+
if self.amount < 0:
|
|
218
|
+
raise ValueError("Amount must be non-negative")
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### 4.7 Modern Stdlib Additions
|
|
222
|
+
|
|
223
|
+
**`StrEnum` (3.11+):** Combine enum membership with string behavior — no need for `.value` in comparisons or string formatting.
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
from enum import StrEnum
|
|
227
|
+
|
|
228
|
+
class Color(StrEnum):
|
|
229
|
+
RED = "red"
|
|
230
|
+
GREEN = "green"
|
|
231
|
+
BLUE = "blue"
|
|
232
|
+
|
|
233
|
+
assert Color.RED == "red" # True — no .value needed
|
|
234
|
+
print(f"Color: {Color.GREEN}") # "Color: green"
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**`tomllib` (3.11+ standard library):** Read TOML files without third-party dependencies; write via `tomli_w` or `tomllib` write support in 3.13+.
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
import tomllib
|
|
241
|
+
|
|
242
|
+
with open("pyproject.toml", "rb") as f: # must open in binary mode
|
|
243
|
+
config = tomllib.load(f)
|
|
244
|
+
|
|
245
|
+
version = config["project"]["version"]
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**`@override` decorator (3.12+, `typing`):** Explicitly mark methods that override a base-class method; type checkers flag mismatches (wrong signature, missing base method).
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
from typing import override
|
|
252
|
+
|
|
253
|
+
class Base:
|
|
254
|
+
def process(self, data: str) -> str:
|
|
255
|
+
return data
|
|
256
|
+
|
|
257
|
+
class Child(Base):
|
|
258
|
+
@override
|
|
259
|
+
def process(self, data: str) -> str: # type checker verifies this overrides Base.process
|
|
260
|
+
return data.strip()
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Use `@override` on every intentional override; it serves as both documentation and a static-analysis safety net.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 5. Async Patterns
|
|
268
|
+
|
|
269
|
+
**Rule:** Use `asyncio` conventions consistently; never mix sync-blocking calls into async code paths.
|
|
270
|
+
|
|
271
|
+
- Prefer `async def` for I/O-bound functions; use `asyncio.to_thread()` to run blocking code in a thread pool.
|
|
272
|
+
- Use `async for` and `async with` for async iteration and context management.
|
|
273
|
+
- Use `asyncio.TaskGroup` (3.11) over `asyncio.gather` for structured concurrency with proper error propagation.
|
|
274
|
+
- Never call `asyncio.sleep(0)` in a busy loop — use proper awaitable primitives.
|
|
275
|
+
- Avoid mixing `asyncio.run()` inside an already-running event loop; use `asyncio.get_event_loop().run_until_complete()` only in legacy contexts.
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
import asyncio
|
|
279
|
+
from pathlib import Path
|
|
280
|
+
|
|
281
|
+
async def fetch_all(urls: list[str]) -> list[bytes]:
|
|
282
|
+
async with asyncio.TaskGroup() as tg:
|
|
283
|
+
tasks = [tg.create_task(fetch(url)) for url in urls]
|
|
284
|
+
return [t.result() for t in tasks]
|
|
285
|
+
|
|
286
|
+
async def read_file_async(path: str) -> str:
|
|
287
|
+
# Run blocking I/O in a thread pool — pass callable, not result
|
|
288
|
+
return await asyncio.to_thread(Path(path).read_text)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## 6. Packaging Best Practices
|
|
294
|
+
|
|
295
|
+
**Rule:** Use `pyproject.toml` as the single configuration file; use `src/` layout.
|
|
296
|
+
|
|
297
|
+
### 6.1 Project Layout
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
my-project/
|
|
301
|
+
src/
|
|
302
|
+
my_package/
|
|
303
|
+
__init__.py
|
|
304
|
+
service.py
|
|
305
|
+
tests/
|
|
306
|
+
test_service.py
|
|
307
|
+
pyproject.toml
|
|
308
|
+
README.md
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
The `src/` layout prevents accidental imports of the development tree; tests always import the installed package.
|
|
312
|
+
|
|
313
|
+
### 6.2 pyproject.toml (PEP 621)
|
|
314
|
+
|
|
315
|
+
```toml
|
|
316
|
+
[build-system]
|
|
317
|
+
requires = ["hatchling"]
|
|
318
|
+
build-backend = "hatchling.build"
|
|
319
|
+
|
|
320
|
+
[project]
|
|
321
|
+
name = "my-package"
|
|
322
|
+
version = "1.0.0"
|
|
323
|
+
requires-python = ">=3.10"
|
|
324
|
+
dependencies = [
|
|
325
|
+
"httpx>=0.27",
|
|
326
|
+
"pydantic>=2.0",
|
|
327
|
+
]
|
|
328
|
+
|
|
329
|
+
[project.optional-dependencies]
|
|
330
|
+
dev = ["pytest>=8", "ruff", "mypy"]
|
|
331
|
+
|
|
332
|
+
[tool.ruff]
|
|
333
|
+
line-length = 100
|
|
334
|
+
target-version = "py310"
|
|
335
|
+
|
|
336
|
+
[tool.mypy]
|
|
337
|
+
python_version = "3.10"
|
|
338
|
+
strict = true
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### 6.3 Recommended Toolchain
|
|
342
|
+
|
|
343
|
+
| Tool | Purpose | Replaces |
|
|
344
|
+
|------|---------|---------|
|
|
345
|
+
| `uv` | Package manager and virtual env (Rust-based, fast) | `pip` + `venv` + `pip-tools` |
|
|
346
|
+
| `ruff` | Linting and formatting | `flake8` + `black` + `isort` |
|
|
347
|
+
| `mypy` or `pyright` | Static type checking | — |
|
|
348
|
+
| `pytest` | Testing framework | `unittest` |
|
|
349
|
+
| `hatchling` | Build backend | `setuptools` |
|
|
350
|
+
|
|
351
|
+
- Use `uv sync` to install from lockfile; `uv add <dep>` to add dependencies with automatic lockfile update.
|
|
352
|
+
- Run `ruff check . --fix` and `ruff format .` in CI to enforce formatting and linting.
|
|
353
|
+
- Enable `mypy --strict` or equivalent `pyright` settings in CI.
|
|
354
|
+
|
|
355
|
+
### 6.4 Virtual Environments
|
|
356
|
+
|
|
357
|
+
Use `uv venv` to create isolated environments; name the directory `.venv` (the conventional default recognized by editors and CI tools).
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
uv venv # creates .venv/ in the current directory
|
|
361
|
+
source .venv/bin/activate # Linux/macOS
|
|
362
|
+
.venv\Scripts\activate # Windows
|
|
363
|
+
uv sync # install dependencies from lockfile into .venv
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
- Commit the `uv.lock` lockfile; add `.venv/` to `.gitignore`.
|
|
367
|
+
- Prefer `uv run <command>` in CI to avoid activating the environment explicitly.
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## 7. Python Version Awareness (3.13 forward-looking)
|
|
372
|
+
|
|
373
|
+
**Python 3.13 (awareness only — not yet required):**
|
|
374
|
+
|
|
375
|
+
- **Free-threaded mode** (`--disable-gil` / `python3.13t`): removes the GIL, enabling true multi-core parallelism in CPython. Do not design code around GIL removal yet; avoid shared mutable state as a general practice.
|
|
376
|
+
- **Improved error messages**: Python 3.13 continues the trend of actionable `TypeError`/`NameError` messages — write tests that do not over-assert on exception message strings.
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Cross-References
|
|
381
|
+
|
|
382
|
+
This skill covers broad Python coding standards. For deeper coverage of specialized domains, refer to:
|
|
383
|
+
|
|
384
|
+
> For Python security best practices (OWASP 2025 aligned), see the `python-security-skill`.
|
|
385
|
+
> For dependency security, supply chain protection, and lockfile management, see the `python-dependency-mgmt` skill.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Python Dependency Management
|
|
3
|
+
description: Standardize Python dependency handling using uv and pip (requirements.txt).
|
|
4
|
+
---
|
|
5
|
+
# Python Dependency Management (uv & pip)
|
|
6
|
+
|
|
7
|
+
This skill ensures consistent and reproducible Python environments using modern tools like `uv` and traditional standards like `requirements.txt`.
|
|
8
|
+
|
|
9
|
+
## Policies
|
|
10
|
+
|
|
11
|
+
### 1. Modern Workflow with `uv`
|
|
12
|
+
* **Rule**: Use `uv` for lightning-fast project management if available.
|
|
13
|
+
* **Action**:
|
|
14
|
+
- Use `uv lock` to generate `uv.lock`.
|
|
15
|
+
- Use `uv sync` to keep the environment in sync with the lockfile.
|
|
16
|
+
- Declare dependencies in `pyproject.toml`.
|
|
17
|
+
* **Rationale**: `uv` is significantly faster than `pip` and provides deterministic builds via lockfiles.
|
|
18
|
+
|
|
19
|
+
### 2. Standardized `requirements.txt`
|
|
20
|
+
* **Rule**: If not using a modern manager, use a layered and pinned `requirements.txt` structure.
|
|
21
|
+
* **Action**:
|
|
22
|
+
- **Layered**: Use `requirements.in` (top-level deps) and `requirements.txt` (fully pinned transitive deps).
|
|
23
|
+
- **Environment Split**: Separate `requirements.txt` from `dev-requirements.txt`.
|
|
24
|
+
- **Hashes**: Generate hashes for security (`--generate-hashes` via `pip-compile`).
|
|
25
|
+
|
|
26
|
+
### 3. Strict Version Pinning
|
|
27
|
+
* **Rule**: All production dependencies must be pinned to a specific version.
|
|
28
|
+
* **Action**: Use `package==1.2.3`, never `package>=1.2.3` in the final lock/txt file.
|
|
29
|
+
|
|
30
|
+
### 4. Virtual Environment Discipline
|
|
31
|
+
* **Rule**: Never install dependencies globally.
|
|
32
|
+
* **Action**:
|
|
33
|
+
- Always create a `.venv` in the project root.
|
|
34
|
+
- For `uv`, it handles this automatically with `uv venv` or implicitly via `uv run`.
|
|
35
|
+
|
|
36
|
+
### 5. Standard Build Systems (PEP 517/518)
|
|
37
|
+
* **Rule**: Use `pyproject.toml` as the source of truth for build metadata.
|
|
38
|
+
|
|
39
|
+
## Tools of Choice
|
|
40
|
+
1. **uv**: (Recommended) Fastest all-in-one manager.
|
|
41
|
+
2. **pip-tools**: For generating pinned `requirements.txt` from `.in` files.
|
|
42
|
+
3. **venv**: Core standard for isolation.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Python Dependency Management Examples
|
|
2
|
+
|
|
3
|
+
### 1. Modern Workspace with `uv`
|
|
4
|
+
**pyproject.toml:**
|
|
5
|
+
```toml
|
|
6
|
+
[project]
|
|
7
|
+
name = "my-app"
|
|
8
|
+
version = "0.1.0"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"requests==2.31.0",
|
|
11
|
+
"structlog>=24.1.0",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[tool.uv]
|
|
15
|
+
managed = true
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Commands:**
|
|
19
|
+
```bash
|
|
20
|
+
# Add a new dependency and update lockfile
|
|
21
|
+
uv add pandas
|
|
22
|
+
|
|
23
|
+
# Run a script within the isolated environment
|
|
24
|
+
uv run main.py
|
|
25
|
+
|
|
26
|
+
# Sync environment with the lockfile
|
|
27
|
+
uv sync
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Traditional `requirements.txt` (pip-tools)
|
|
31
|
+
**requirements.in:**
|
|
32
|
+
```text
|
|
33
|
+
flask
|
|
34
|
+
psycopg2-binary
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Workflow:**
|
|
38
|
+
```bash
|
|
39
|
+
# Generate pinned requirements.txt with hashes
|
|
40
|
+
pip-compile --generate-hashes requirements.in
|
|
41
|
+
|
|
42
|
+
# Install exactly what is pinned
|
|
43
|
+
pip install -r requirements.txt
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. Development vs Production Deps
|
|
47
|
+
**dev-requirements.in:**
|
|
48
|
+
```text
|
|
49
|
+
-c requirements.txt
|
|
50
|
+
pytest
|
|
51
|
+
black
|
|
52
|
+
ruff
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Generate dev-requirements.txt
|
|
57
|
+
pip-compile dev-requirements.in
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 4. Virtual Environment Setup (Standard)
|
|
61
|
+
```bash
|
|
62
|
+
python -m venv .venv
|
|
63
|
+
# Linux/macOS
|
|
64
|
+
source .venv/bin/activate
|
|
65
|
+
# Windows
|
|
66
|
+
.venv\Scripts\activate
|
|
67
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Python Security Best Practices
|
|
3
|
+
description: Enforce secure Python coding standards following OWASP Top 10 2025.
|
|
4
|
+
---
|
|
5
|
+
# Python Security Best Practices (OWASP 2025 aligned)
|
|
6
|
+
|
|
7
|
+
This skill provides mandatory security guardrails for Python applications, ensuring protection against common vulnerabilities and alignment with OWASP Top 10 standards.
|
|
8
|
+
|
|
9
|
+
## Policies
|
|
10
|
+
|
|
11
|
+
### 1. Zero Insecure Function Usage
|
|
12
|
+
* **Rule**: Ban functions that allow arbitrary code execution or insecure OS commands.
|
|
13
|
+
* **Action**:
|
|
14
|
+
- NEVER use `eval()` or `exec()`.
|
|
15
|
+
- Avoid `subprocess.run(..., shell=True)`. Use lists for commands instead.
|
|
16
|
+
- Avoid `yaml.load()` without specifying a loader (use `yaml.safe_load()`).
|
|
17
|
+
|
|
18
|
+
### 2. Secure Data Serialization
|
|
19
|
+
* **Rule**: Protect against insecure deserialization.
|
|
20
|
+
* - **Action**:
|
|
21
|
+
- NEVER use `pickle` for untrusted data. Use `json` instead.
|
|
22
|
+
- Be cautious with `xml.etree.ElementTree` (vulnerable to XXE); use `defusedxml` if possible.
|
|
23
|
+
|
|
24
|
+
### 3. Injection Prevention (A05:2025)
|
|
25
|
+
* **Rule**: Use parameterized queries for all database and API interactions.
|
|
26
|
+
* **Action**:
|
|
27
|
+
- Never use f-strings or `.format()` for SQL queries.
|
|
28
|
+
- Use ORM features (Django ORM, SQLAlchemy) or parameter placeholders (`%s`, `?`).
|
|
29
|
+
|
|
30
|
+
### 4. Cryptographic Standards (A04:2025)
|
|
31
|
+
* **Rule**: Use modern, collision-resistant hashing and encryption.
|
|
32
|
+
* **Action**:
|
|
33
|
+
- Use `hashlib.sha256()` or better. Ban MD5 and SHA1.
|
|
34
|
+
- Use `secrets` module for tokens/passwords, not `random`.
|
|
35
|
+
|
|
36
|
+
### 5. Dependency Integrity (A03:2025)
|
|
37
|
+
* **Rule**: Lock dependencies and scan for known vulnerabilities.
|
|
38
|
+
* **Action**:
|
|
39
|
+
- Always commit lockfiles (`uv.lock`, `poetry.lock`, or `requirements.txt` with hashes).
|
|
40
|
+
- Periodically run `pip-audit` or `safety`.
|
|
41
|
+
|
|
42
|
+
### 6. Secure Error Handling (A10:2025)
|
|
43
|
+
* **Rule**: Do not leak sensitive information in tracebacks or logs.
|
|
44
|
+
* **Action**:
|
|
45
|
+
- Never log `pydantic` models or raw request bodies containing PII/Secrets.
|
|
46
|
+
- Use generic error messages for end-users while keeping detailed logs internally.
|
|
47
|
+
|
|
48
|
+
## Python Security Mapping (OWASP 2025)
|
|
49
|
+
|
|
50
|
+
| Category | Python Vulnerability | Secure Alternative |
|
|
51
|
+
| :--- | :--- | :--- |
|
|
52
|
+
| **A01: Access Control** | URL hijacking in `requests` | Validate redirect targets |
|
|
53
|
+
| **A02: Configuration** | Debug mode in Flask/Django | `DEBUG = False` in production |
|
|
54
|
+
| **A03: Supply Chain** | Typosquatting/Old deps | Pin versions + `pip-audit` |
|
|
55
|
+
| **A05: Injection** | `os.system()` / RAW SQL | `subprocess.run()` list / ORM |
|
|
56
|
+
| **A08: Integrity** | `pickle.load()` | `json.loads()` |
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Python Security Examples
|
|
2
|
+
|
|
3
|
+
### 1. Secure Subprocess (Avoiding Injection)
|
|
4
|
+
**Dangerous:**
|
|
5
|
+
```python
|
|
6
|
+
import os
|
|
7
|
+
def delete_file(filename):
|
|
8
|
+
os.system(f"rm -rf {filename}") # VULNERABLE to injection
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Secure:**
|
|
12
|
+
```python
|
|
13
|
+
import subprocess
|
|
14
|
+
def delete_file(filename):
|
|
15
|
+
# Pass as a list, shell=False by default
|
|
16
|
+
subprocess.run(["rm", "-rf", filename], check=True)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### 2. Secure Serialization
|
|
20
|
+
**Dangerous:**
|
|
21
|
+
```python
|
|
22
|
+
import pickle
|
|
23
|
+
def load_user(data):
|
|
24
|
+
return pickle.loads(data) # VULNERABLE to arbitrary code execution
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Secure:**
|
|
28
|
+
```python
|
|
29
|
+
import json
|
|
30
|
+
def load_user(data):
|
|
31
|
+
return json.loads(data) # Safe for untrusted input
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 3. Preventing SQL Injection
|
|
35
|
+
**Dangerous:**
|
|
36
|
+
```python
|
|
37
|
+
cursor.execute(f"SELECT * FROM users WHERE id = '{user_id}'")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Secure:**
|
|
41
|
+
```python
|
|
42
|
+
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 4. Secure Randomness
|
|
46
|
+
**Dangerous:**
|
|
47
|
+
```python
|
|
48
|
+
import random
|
|
49
|
+
token = str(random.random()) # Predictable
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Secure:**
|
|
53
|
+
```python
|
|
54
|
+
import secrets
|
|
55
|
+
token = secrets.token_urlsafe(32) # Cryptographically secure
|
|
56
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Self-Signed Certificate Generator
|
|
3
|
+
description: Generates secure self-signed certificates and Root CAs using OpenSSL.
|
|
4
|
+
---
|
|
5
|
+
# Self-Signed Certificate Generator
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
Automate the creation of Root CAs and self-signed certificates for internal services, local development, and testing environments.
|
|
9
|
+
|
|
10
|
+
## Instructions
|
|
11
|
+
1. **Environment Check**: Ensure `openssl` is installed and available in the PATH.
|
|
12
|
+
2. **Workflow Selection**:
|
|
13
|
+
- **Standalone Self-Signed**: Quickest for single service testing.
|
|
14
|
+
- **Root CA + Signed Cert**: Recommended for internal architectures where multiple services need to trust a single authority.
|
|
15
|
+
3. **Security Standards**:
|
|
16
|
+
- Key Size: Minimum 2048-bit (4096-bit preferred).
|
|
17
|
+
- Hashing: SHA-256 or higher.
|
|
18
|
+
- Permissions: Private keys must be set to `600`.
|
|
19
|
+
|
|
20
|
+
## Rules
|
|
21
|
+
- NEVER store private keys in version control.
|
|
22
|
+
- ALWAYS include Subject Alternative Names (SANs) for modern browser compatibility.
|
|
23
|
+
- Ensure the certificate Common Name (CN) matches the intended hostname.
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
The skill provide both Bash (Linux/macOS) and PowerShell (Windows) scripts.
|
|
27
|
+
|
|
28
|
+
### Linux / macOS
|
|
29
|
+
Run `scripts/generate-cert.sh` with:
|
|
30
|
+
- `TYPE`: `root` or `cert`
|
|
31
|
+
- `NAME`: Base name for the files
|
|
32
|
+
- `DNS`: Primary domain/IP
|
|
33
|
+
|
|
34
|
+
Example: `bash scripts/generate-cert.sh cert my-service localhost`
|
|
35
|
+
|
|
36
|
+
### Windows (PowerShell)
|
|
37
|
+
Run `scripts/generate-cert.ps1` with:
|
|
38
|
+
- `-Type`: `root` or `cert`
|
|
39
|
+
- `-Name`: Base name
|
|
40
|
+
- `-Dns`: Primary domain/IP
|
|
41
|
+
|
|
42
|
+
Example: `.\scripts\generate-cert.ps1 -Type cert -Name my-service -Dns localhost`
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
param (
|
|
2
|
+
[Parameter(Mandatory=$true)]
|
|
3
|
+
[ValidateSet("root", "cert")]
|
|
4
|
+
[string]$Type,
|
|
5
|
+
|
|
6
|
+
[string]$Name = "server",
|
|
7
|
+
|
|
8
|
+
[string]$Dns = "localhost",
|
|
9
|
+
|
|
10
|
+
[string]$CaKey,
|
|
11
|
+
|
|
12
|
+
[string]$CaCert
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
$ErrorActionPreference = "Stop"
|
|
16
|
+
|
|
17
|
+
if ($Type -eq "root") {
|
|
18
|
+
Write-Host "Generating Root CA..." -ForegroundColor Cyan
|
|
19
|
+
openssl genrsa -out "${Name}_rootCA.key" 4096
|
|
20
|
+
openssl req -x509 -new -nodes -key "${Name}_rootCA.key" -sha256 -days 3650 -out "${Name}_rootCA.crt" `
|
|
21
|
+
-subj "/CN=${Name}-Root-CA/O=MA-Agents/C=US"
|
|
22
|
+
Write-Host "Root CA created: ${Name}_rootCA.crt" -ForegroundColor Green
|
|
23
|
+
|
|
24
|
+
} elseif ($Type -eq "cert") {
|
|
25
|
+
if (-not $CaKey -or -not $CaCert) {
|
|
26
|
+
Write-Host "Generating standalone self-signed certificate..." -ForegroundColor Cyan
|
|
27
|
+
openssl req -x509 -newnodes -days 365 -newkey rsa:2048 `
|
|
28
|
+
-keyout "${Name}.key" -out "${Name}.crt" `
|
|
29
|
+
-subj "/CN=${Dns}/O=MA-Agents" `
|
|
30
|
+
-addext "subjectAltName = DNS:${Dns}"
|
|
31
|
+
} else {
|
|
32
|
+
Write-Host "Generating certificate signed by CA..." -ForegroundColor Cyan
|
|
33
|
+
openssl genrsa -out "${Name}.key" 2048
|
|
34
|
+
openssl req -new -key "${Name}.key" -out "${Name}.csr" -subj "/CN=${Dns}/O=MA-Agents"
|
|
35
|
+
|
|
36
|
+
# Extension file for SAN
|
|
37
|
+
"subjectAltName = DNS:${Dns}" | Out-File -FilePath "${Name}.ext" -Encoding ascii
|
|
38
|
+
|
|
39
|
+
openssl x509 -req -in "${Name}.csr" -CA "$CaCert" -CAkey "$CaKey" -CAcreateserial `
|
|
40
|
+
-out "${Name}.crt" -days 365 -sha256 -extfile "${Name}.ext"
|
|
41
|
+
|
|
42
|
+
Remove-Item "${Name}.csr", "${Name}.ext" -ErrorAction SilentlyContinue
|
|
43
|
+
}
|
|
44
|
+
Write-Host "Certificate created: ${Name}.crt" -ForegroundColor Green
|
|
45
|
+
}
|