claude-mpm 4.16.3__py3-none-any.whl → 4.17.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/commands/mpm-help.md +3 -0
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +97 -9
- {claude_mpm-4.16.3.dist-info → claude_mpm-4.17.1.dist-info}/METADATA +7 -2
- {claude_mpm-4.16.3.dist-info → claude_mpm-4.17.1.dist-info}/RECORD +32 -11
- {claude_mpm-4.16.3.dist-info → claude_mpm-4.17.1.dist-info}/WHEEL +0 -0
- {claude_mpm-4.16.3.dist-info → claude_mpm-4.17.1.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.16.3.dist-info → claude_mpm-4.17.1.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.16.3.dist-info → claude_mpm-4.17.1.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.17.1
|
claude_mpm/commands/mpm-help.md
CHANGED
|
@@ -90,6 +90,9 @@ Available Commands:
|
|
|
90
90
|
/mpm-monitor [start|stop|restart|status|port]
|
|
91
91
|
Manage Socket.IO monitoring server and dashboard
|
|
92
92
|
|
|
93
|
+
/mpm-version
|
|
94
|
+
Display comprehensive version information including project version, all agents with versions, and all skills with versions
|
|
95
|
+
|
|
93
96
|
Use '/mpm-help <command>' for detailed help on a specific command.
|
|
94
97
|
```
|
|
95
98
|
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Display Claude MPM Version Information
|
|
2
|
+
|
|
3
|
+
Show comprehensive version information for Claude MPM project, agents, and skills.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/mpm-version
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Description
|
|
12
|
+
|
|
13
|
+
Display version information including:
|
|
14
|
+
- Project version and build number
|
|
15
|
+
- All deployed agents with their versions (grouped by tier: system/user/project)
|
|
16
|
+
- All available skills with their versions (grouped by source: bundled/user/project)
|
|
17
|
+
- Summary statistics
|
|
18
|
+
|
|
19
|
+
## Implementation
|
|
20
|
+
|
|
21
|
+
When you run `/mpm-version`, the PM will:
|
|
22
|
+
|
|
23
|
+
1. **Collect Version Information**
|
|
24
|
+
- Use VersionService to gather all version data
|
|
25
|
+
- Project version from pyproject.toml
|
|
26
|
+
- Build number from BUILD_NUMBER file
|
|
27
|
+
- Agent versions from AgentRegistry
|
|
28
|
+
- Skills versions from SkillRegistry
|
|
29
|
+
|
|
30
|
+
2. **Format Output**
|
|
31
|
+
- Hierarchical display: Project → Agents → Skills
|
|
32
|
+
- Grouped by tier/source for clarity
|
|
33
|
+
- Sorted alphabetically within groups
|
|
34
|
+
- Summary statistics at the end
|
|
35
|
+
|
|
36
|
+
3. **Display Results**
|
|
37
|
+
- Well-formatted tree structure
|
|
38
|
+
- Easy to scan and read
|
|
39
|
+
- Includes totals and counts
|
|
40
|
+
|
|
41
|
+
## Example Output
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
Claude MPM Version Information
|
|
45
|
+
==============================
|
|
46
|
+
|
|
47
|
+
Project Version: 4.16.3
|
|
48
|
+
Build: 481
|
|
49
|
+
|
|
50
|
+
Agents (35 total)
|
|
51
|
+
-----------------
|
|
52
|
+
|
|
53
|
+
System Agents (30):
|
|
54
|
+
├─ agent-manager (1.0.0)
|
|
55
|
+
├─ engineer (3.9.1)
|
|
56
|
+
├─ research-agent (4.5.1)
|
|
57
|
+
├─ documentation (2.1.0)
|
|
58
|
+
├─ qa (2.0.3)
|
|
59
|
+
└─ ... (25 more)
|
|
60
|
+
|
|
61
|
+
User Agents (3):
|
|
62
|
+
├─ custom-agent (1.0.0)
|
|
63
|
+
├─ testing-agent (0.5.0)
|
|
64
|
+
└─ prototype-agent (0.1.0)
|
|
65
|
+
|
|
66
|
+
Project Agents (2):
|
|
67
|
+
├─ project-specific (2.0.0)
|
|
68
|
+
└─ domain-expert (1.1.0)
|
|
69
|
+
|
|
70
|
+
Skills (20 total)
|
|
71
|
+
-----------------
|
|
72
|
+
|
|
73
|
+
Bundled Skills (20):
|
|
74
|
+
├─ test-driven-development (0.1.0)
|
|
75
|
+
├─ systematic-debugging (0.1.0)
|
|
76
|
+
├─ async-testing (0.1.0)
|
|
77
|
+
├─ performance-profiling (0.1.0)
|
|
78
|
+
├─ security-scanning (0.1.0)
|
|
79
|
+
└─ ... (15 more)
|
|
80
|
+
|
|
81
|
+
User Skills (0):
|
|
82
|
+
(none)
|
|
83
|
+
|
|
84
|
+
Project Skills (0):
|
|
85
|
+
(none)
|
|
86
|
+
|
|
87
|
+
Summary
|
|
88
|
+
-------
|
|
89
|
+
• Project: v4.16.3 (build 481)
|
|
90
|
+
• Agents: 35 total (30 system, 3 user, 2 project)
|
|
91
|
+
• Skills: 20 total (20 bundled, 0 user, 0 project)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## PM Implementation Instructions
|
|
95
|
+
|
|
96
|
+
To execute this command, PM should:
|
|
97
|
+
|
|
98
|
+
1. Import and use VersionService:
|
|
99
|
+
```python
|
|
100
|
+
from claude_mpm.services.version_service import VersionService
|
|
101
|
+
|
|
102
|
+
service = VersionService()
|
|
103
|
+
summary = service.get_version_summary()
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
2. Format output following the example structure above
|
|
107
|
+
3. Handle missing data gracefully (show "unknown" for missing versions)
|
|
108
|
+
4. Include all tiers/sources even if counts are zero
|
|
109
|
+
|
|
110
|
+
## Related Commands
|
|
111
|
+
|
|
112
|
+
- `/mpm-help` - Show all available MPM commands
|
|
113
|
+
- `/mpm-status` - Show system status information
|
claude_mpm/commands/mpm.md
CHANGED
|
@@ -8,6 +8,7 @@ Available MPM commands:
|
|
|
8
8
|
- /mpm-help - Show command help
|
|
9
9
|
- /mpm-status - Show MPM status
|
|
10
10
|
- /mpm-config - Manage configuration
|
|
11
|
+
- /mpm-version - Display version information for project, agents, and skills
|
|
11
12
|
|
|
12
13
|
Claude MPM extends Claude Code with:
|
|
13
14
|
- Multi-agent orchestration
|
|
@@ -9,7 +9,7 @@ Extracted from ClaudeRunner to follow Single Responsibility Principle.
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Any, Dict, Optional
|
|
12
|
+
from typing import Any, Dict, List, Optional
|
|
13
13
|
|
|
14
14
|
from claude_mpm.config.paths import paths
|
|
15
15
|
from claude_mpm.core.base_service import BaseService
|
|
@@ -274,3 +274,106 @@ class VersionService(BaseService, VersionServiceInterface):
|
|
|
274
274
|
"message": "Update checking not implemented",
|
|
275
275
|
"checked_at": None,
|
|
276
276
|
}
|
|
277
|
+
|
|
278
|
+
def get_agents_versions(self) -> Dict[str, List[Dict[str, str]]]:
|
|
279
|
+
"""Get all agents grouped by tier with versions.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
Dict with keys: system, user, project
|
|
283
|
+
Each value is list of agent dicts with: name, version, id
|
|
284
|
+
"""
|
|
285
|
+
from claude_mpm.core.unified_agent_registry import get_agent_registry
|
|
286
|
+
|
|
287
|
+
agents_by_tier = {"system": [], "user": [], "project": []}
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
registry = get_agent_registry()
|
|
291
|
+
all_agents = registry.list_agents()
|
|
292
|
+
|
|
293
|
+
for agent in all_agents:
|
|
294
|
+
agent_info = {
|
|
295
|
+
"name": agent.name,
|
|
296
|
+
"version": agent.version,
|
|
297
|
+
"id": agent.name, # Use name as ID since agent_id doesn't exist
|
|
298
|
+
}
|
|
299
|
+
tier = (
|
|
300
|
+
agent.tier.value
|
|
301
|
+
if hasattr(agent.tier, "value")
|
|
302
|
+
else str(agent.tier)
|
|
303
|
+
)
|
|
304
|
+
if tier in agents_by_tier:
|
|
305
|
+
agents_by_tier[tier].append(agent_info)
|
|
306
|
+
else:
|
|
307
|
+
agents_by_tier["system"].append(agent_info)
|
|
308
|
+
|
|
309
|
+
# Sort each tier alphabetically by name
|
|
310
|
+
for tier, agents in agents_by_tier.items():
|
|
311
|
+
agents.sort(key=lambda x: x["name"])
|
|
312
|
+
|
|
313
|
+
except Exception as e:
|
|
314
|
+
self.logger.error(f"Failed to get agent versions: {e}")
|
|
315
|
+
|
|
316
|
+
return agents_by_tier
|
|
317
|
+
|
|
318
|
+
def get_skills_versions(self) -> Dict[str, List[Dict[str, str]]]:
|
|
319
|
+
"""Get all skills grouped by source with versions.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
Dict with keys: bundled, user, project
|
|
323
|
+
Each value is list of skill dicts with: name, version, description
|
|
324
|
+
"""
|
|
325
|
+
from claude_mpm.skills.registry import get_registry
|
|
326
|
+
|
|
327
|
+
skills_by_source = {"bundled": [], "user": [], "project": []}
|
|
328
|
+
|
|
329
|
+
try:
|
|
330
|
+
registry = get_registry()
|
|
331
|
+
|
|
332
|
+
for skill in registry.list_skills():
|
|
333
|
+
skill_info = {
|
|
334
|
+
"name": skill.name,
|
|
335
|
+
"version": skill.version,
|
|
336
|
+
"description": (
|
|
337
|
+
skill.description[:60] + "..."
|
|
338
|
+
if len(skill.description) > 60
|
|
339
|
+
else skill.description
|
|
340
|
+
),
|
|
341
|
+
}
|
|
342
|
+
source = skill.source if skill.source in skills_by_source else "bundled"
|
|
343
|
+
skills_by_source[source].append(skill_info)
|
|
344
|
+
|
|
345
|
+
# Sort each source alphabetically by name
|
|
346
|
+
for source, skills in skills_by_source.items():
|
|
347
|
+
skills.sort(key=lambda x: x["name"])
|
|
348
|
+
|
|
349
|
+
except Exception as e:
|
|
350
|
+
self.logger.error(f"Failed to get skill versions: {e}")
|
|
351
|
+
|
|
352
|
+
return skills_by_source
|
|
353
|
+
|
|
354
|
+
def get_version_summary(self) -> Dict:
|
|
355
|
+
"""Get complete version summary.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
Dict with project_version, build, agents, skills, and counts
|
|
359
|
+
"""
|
|
360
|
+
agents = self.get_agents_versions()
|
|
361
|
+
skills = self.get_skills_versions()
|
|
362
|
+
build = self.get_build_number()
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
"project_version": self.get_base_version(),
|
|
366
|
+
"build": build,
|
|
367
|
+
"agents": agents,
|
|
368
|
+
"skills": skills,
|
|
369
|
+
"counts": {
|
|
370
|
+
"agents_total": sum(len(v) for v in agents.values()),
|
|
371
|
+
"agents_system": len(agents.get("system", [])),
|
|
372
|
+
"agents_user": len(agents.get("user", [])),
|
|
373
|
+
"agents_project": len(agents.get("project", [])),
|
|
374
|
+
"skills_total": sum(len(v) for v in skills.values()),
|
|
375
|
+
"skills_bundled": len(skills.get("bundled", [])),
|
|
376
|
+
"skills_user": len(skills.get("user", [])),
|
|
377
|
+
"skills_project": len(skills.get("project", [])),
|
|
378
|
+
},
|
|
379
|
+
}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
---
|
|
2
|
+
skill_id: api-documentation
|
|
3
|
+
skill_version: 0.1.0
|
|
4
|
+
description: Best practices for documenting APIs and code interfaces, eliminating redundant documentation guidance per agent.
|
|
5
|
+
updated_at: 2025-10-30T17:00:00Z
|
|
6
|
+
tags: [api, documentation, best-practices, interfaces]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# API Documentation
|
|
10
|
+
|
|
11
|
+
Best practices for documenting APIs and code interfaces. Eliminates ~100-150 lines of redundant documentation guidance per agent.
|
|
12
|
+
|
|
13
|
+
## Core Documentation Principles
|
|
14
|
+
|
|
15
|
+
1. **Document the why, not just the what** - Explain intent and rationale
|
|
16
|
+
2. **Keep docs close to code** - Inline documentation stays synchronized
|
|
17
|
+
3. **Document contracts, not implementation** - Focus on behavior
|
|
18
|
+
4. **Examples are essential** - Show real usage
|
|
19
|
+
5. **Update docs with code** - Outdated docs are worse than no docs
|
|
20
|
+
|
|
21
|
+
## Function/Method Documentation
|
|
22
|
+
|
|
23
|
+
### Python (Docstrings)
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
def calculate_discount(price: float, discount_percent: float) -> float:
|
|
27
|
+
"""
|
|
28
|
+
Calculate discounted price with percentage off.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
price: Original price in dollars (must be positive)
|
|
32
|
+
discount_percent: Discount percentage (0-100)
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Final price after discount, rounded to 2 decimals
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
ValueError: If price is negative or discount > 100
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
>>> calculate_discount(100.0, 20.0)
|
|
42
|
+
80.0
|
|
43
|
+
>>> calculate_discount(50.0, 50.0)
|
|
44
|
+
25.0
|
|
45
|
+
|
|
46
|
+
Note:
|
|
47
|
+
Discount percent is capped at 100% (minimum price of 0)
|
|
48
|
+
"""
|
|
49
|
+
if price < 0:
|
|
50
|
+
raise ValueError("Price cannot be negative")
|
|
51
|
+
if discount_percent > 100:
|
|
52
|
+
raise ValueError("Discount cannot exceed 100%")
|
|
53
|
+
|
|
54
|
+
discount_amount = price * (discount_percent / 100)
|
|
55
|
+
return round(price - discount_amount, 2)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### JavaScript (JSDoc)
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
/**
|
|
62
|
+
* Calculate discounted price with percentage off
|
|
63
|
+
*
|
|
64
|
+
* @param {number} price - Original price in dollars (must be positive)
|
|
65
|
+
* @param {number} discountPercent - Discount percentage (0-100)
|
|
66
|
+
* @returns {number} Final price after discount, rounded to 2 decimals
|
|
67
|
+
* @throws {Error} If price is negative or discount > 100
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* calculateDiscount(100.0, 20.0)
|
|
71
|
+
* // returns 80.0
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* calculateDiscount(50.0, 50.0)
|
|
75
|
+
* // returns 25.0
|
|
76
|
+
*/
|
|
77
|
+
function calculateDiscount(price, discountPercent) {
|
|
78
|
+
if (price < 0) {
|
|
79
|
+
throw new Error('Price cannot be negative');
|
|
80
|
+
}
|
|
81
|
+
if (discountPercent > 100) {
|
|
82
|
+
throw new Error('Discount cannot exceed 100%');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const discountAmount = price * (discountPercent / 100);
|
|
86
|
+
return Math.round((price - discountAmount) * 100) / 100;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Go (Godoc)
|
|
91
|
+
|
|
92
|
+
```go
|
|
93
|
+
// CalculateDiscount calculates discounted price with percentage off.
|
|
94
|
+
//
|
|
95
|
+
// The function applies the given discount percentage to the original price
|
|
96
|
+
// and returns the final price rounded to 2 decimal places.
|
|
97
|
+
//
|
|
98
|
+
// Parameters:
|
|
99
|
+
// - price: Original price in dollars (must be positive)
|
|
100
|
+
// - discountPercent: Discount percentage (0-100)
|
|
101
|
+
//
|
|
102
|
+
// Returns the final price after discount.
|
|
103
|
+
//
|
|
104
|
+
// Returns an error if price is negative or discount exceeds 100%.
|
|
105
|
+
//
|
|
106
|
+
// Example:
|
|
107
|
+
//
|
|
108
|
+
// finalPrice, err := CalculateDiscount(100.0, 20.0)
|
|
109
|
+
// // finalPrice = 80.0
|
|
110
|
+
func CalculateDiscount(price, discountPercent float64) (float64, error) {
|
|
111
|
+
if price < 0 {
|
|
112
|
+
return 0, errors.New("price cannot be negative")
|
|
113
|
+
}
|
|
114
|
+
if discountPercent > 100 {
|
|
115
|
+
return 0, errors.New("discount cannot exceed 100%")
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
discountAmount := price * (discountPercent / 100)
|
|
119
|
+
return math.Round((price-discountAmount)*100) / 100, nil
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## API Endpoint Documentation
|
|
124
|
+
|
|
125
|
+
### REST API (OpenAPI/Swagger)
|
|
126
|
+
|
|
127
|
+
```yaml
|
|
128
|
+
openapi: 3.0.0
|
|
129
|
+
info:
|
|
130
|
+
title: User Management API
|
|
131
|
+
version: 1.0.0
|
|
132
|
+
|
|
133
|
+
paths:
|
|
134
|
+
/users/{userId}:
|
|
135
|
+
get:
|
|
136
|
+
summary: Get user by ID
|
|
137
|
+
description: Retrieves detailed information for a specific user
|
|
138
|
+
parameters:
|
|
139
|
+
- name: userId
|
|
140
|
+
in: path
|
|
141
|
+
required: true
|
|
142
|
+
schema:
|
|
143
|
+
type: integer
|
|
144
|
+
minimum: 1
|
|
145
|
+
description: Unique user identifier
|
|
146
|
+
responses:
|
|
147
|
+
'200':
|
|
148
|
+
description: User found successfully
|
|
149
|
+
content:
|
|
150
|
+
application/json:
|
|
151
|
+
schema:
|
|
152
|
+
$ref: '#/components/schemas/User'
|
|
153
|
+
example:
|
|
154
|
+
id: 123
|
|
155
|
+
name: "John Doe"
|
|
156
|
+
email: "john@example.com"
|
|
157
|
+
'404':
|
|
158
|
+
description: User not found
|
|
159
|
+
'401':
|
|
160
|
+
description: Unauthorized - authentication required
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### GraphQL
|
|
164
|
+
|
|
165
|
+
```graphql
|
|
166
|
+
"""
|
|
167
|
+
Represents a user in the system
|
|
168
|
+
"""
|
|
169
|
+
type User {
|
|
170
|
+
"""Unique identifier for the user"""
|
|
171
|
+
id: ID!
|
|
172
|
+
|
|
173
|
+
"""User's full name"""
|
|
174
|
+
name: String!
|
|
175
|
+
|
|
176
|
+
"""User's email address (validated)"""
|
|
177
|
+
email: String!
|
|
178
|
+
|
|
179
|
+
"""User's posts (paginated)"""
|
|
180
|
+
posts(limit: Int = 10, offset: Int = 0): [Post!]!
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
"""
|
|
184
|
+
Query a specific user by ID
|
|
185
|
+
"""
|
|
186
|
+
type Query {
|
|
187
|
+
"""
|
|
188
|
+
Get user by unique identifier
|
|
189
|
+
|
|
190
|
+
Returns null if user not found
|
|
191
|
+
"""
|
|
192
|
+
user(id: ID!): User
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Class/Module Documentation
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
class UserManager:
|
|
200
|
+
"""
|
|
201
|
+
Manages user accounts and authentication.
|
|
202
|
+
|
|
203
|
+
This class provides a high-level interface for user management
|
|
204
|
+
operations including creation, authentication, and profile updates.
|
|
205
|
+
|
|
206
|
+
Attributes:
|
|
207
|
+
db: Database connection instance
|
|
208
|
+
cache: Redis cache for session management
|
|
209
|
+
|
|
210
|
+
Example:
|
|
211
|
+
>>> manager = UserManager(db=get_db(), cache=get_cache())
|
|
212
|
+
>>> user = manager.create_user("john@example.com", "password")
|
|
213
|
+
>>> authenticated = manager.authenticate("john@example.com", "password")
|
|
214
|
+
>>> authenticated is not None
|
|
215
|
+
True
|
|
216
|
+
|
|
217
|
+
Thread Safety:
|
|
218
|
+
This class is thread-safe. Multiple threads can safely call
|
|
219
|
+
methods concurrently.
|
|
220
|
+
|
|
221
|
+
Note:
|
|
222
|
+
All passwords are automatically hashed using bcrypt before
|
|
223
|
+
storage. Never pass pre-hashed passwords to methods.
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
def __init__(self, db: Database, cache: Cache):
|
|
227
|
+
"""
|
|
228
|
+
Initialize UserManager with database and cache.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
db: Database connection for persistent storage
|
|
232
|
+
cache: Redis cache for session management
|
|
233
|
+
|
|
234
|
+
Raises:
|
|
235
|
+
ConnectionError: If unable to connect to database or cache
|
|
236
|
+
"""
|
|
237
|
+
self.db = db
|
|
238
|
+
self.cache = cache
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## README Documentation Structure
|
|
242
|
+
|
|
243
|
+
```markdown
|
|
244
|
+
# Project Name
|
|
245
|
+
|
|
246
|
+
Brief description of what the project does (1-2 sentences).
|
|
247
|
+
|
|
248
|
+
## Features
|
|
249
|
+
|
|
250
|
+
- Key feature 1
|
|
251
|
+
- Key feature 2
|
|
252
|
+
- Key feature 3
|
|
253
|
+
|
|
254
|
+
## Installation
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
pip install project-name
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Quick Start
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
from project import MainClass
|
|
264
|
+
|
|
265
|
+
# Simple usage example
|
|
266
|
+
client = MainClass(api_key="your-key")
|
|
267
|
+
result = client.do_something()
|
|
268
|
+
print(result)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Configuration
|
|
272
|
+
|
|
273
|
+
| Option | Type | Default | Description |
|
|
274
|
+
|--------|------|---------|-------------|
|
|
275
|
+
| `api_key` | str | None | API authentication key |
|
|
276
|
+
| `timeout` | int | 30 | Request timeout in seconds |
|
|
277
|
+
|
|
278
|
+
## API Reference
|
|
279
|
+
|
|
280
|
+
See full [API Documentation](docs/api.md)
|
|
281
|
+
|
|
282
|
+
### Main Methods
|
|
283
|
+
|
|
284
|
+
#### `do_something(param1, param2)`
|
|
285
|
+
|
|
286
|
+
Description of what this does.
|
|
287
|
+
|
|
288
|
+
**Parameters:**
|
|
289
|
+
- `param1` (str): Description of param1
|
|
290
|
+
- `param2` (int): Description of param2
|
|
291
|
+
|
|
292
|
+
**Returns:** Description of return value
|
|
293
|
+
|
|
294
|
+
**Example:**
|
|
295
|
+
```python
|
|
296
|
+
result = client.do_something("value", 42)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Contributing
|
|
300
|
+
|
|
301
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
302
|
+
|
|
303
|
+
## License
|
|
304
|
+
|
|
305
|
+
MIT License - see [LICENSE](LICENSE)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Documentation Anti-Patterns
|
|
309
|
+
|
|
310
|
+
### ❌ Redundant Comments
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
# Bad: Obvious comment adds no value
|
|
314
|
+
i = i + 1 # Increment i
|
|
315
|
+
|
|
316
|
+
# Good: Comment explains WHY
|
|
317
|
+
i = i + 1 # Skip header row
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### ❌ Outdated Documentation
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
# Bad: Comment doesn't match code
|
|
324
|
+
def get_users(limit=10): # Comment says: Returns all users
|
|
325
|
+
"""Returns all users in the system.""" # But limit is 10!
|
|
326
|
+
return User.query.limit(limit).all()
|
|
327
|
+
|
|
328
|
+
# Good: Keep docs synchronized
|
|
329
|
+
def get_users(limit=10):
|
|
330
|
+
"""
|
|
331
|
+
Returns up to 'limit' users from the system.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
limit: Maximum number of users to return (default: 10)
|
|
335
|
+
"""
|
|
336
|
+
return User.query.limit(limit).all()
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### ❌ Implementation Documentation
|
|
340
|
+
|
|
341
|
+
```python
|
|
342
|
+
# Bad: Documents HOW (implementation)
|
|
343
|
+
def sort_users(users):
|
|
344
|
+
"""Uses bubble sort algorithm to sort users.""" # Don't care!
|
|
345
|
+
...
|
|
346
|
+
|
|
347
|
+
# Good: Documents WHAT (contract)
|
|
348
|
+
def sort_users(users):
|
|
349
|
+
"""Returns users sorted alphabetically by name."""
|
|
350
|
+
...
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Documentation Tools
|
|
354
|
+
|
|
355
|
+
### Python
|
|
356
|
+
- **Sphinx**: Generate HTML docs from docstrings
|
|
357
|
+
- **pdoc**: Simpler alternative to Sphinx
|
|
358
|
+
- **MkDocs**: Markdown-based documentation
|
|
359
|
+
|
|
360
|
+
### JavaScript
|
|
361
|
+
- **JSDoc**: Generate HTML from JSDoc comments
|
|
362
|
+
- **TypeDoc**: For TypeScript projects
|
|
363
|
+
- **Docusaurus**: Full documentation websites
|
|
364
|
+
|
|
365
|
+
### Go
|
|
366
|
+
- **godoc**: Built-in documentation tool
|
|
367
|
+
- **pkgsite**: Go package documentation
|
|
368
|
+
|
|
369
|
+
### Rust
|
|
370
|
+
- **rustdoc**: Built-in documentation with `cargo doc`
|
|
371
|
+
|
|
372
|
+
## Quick Documentation Checklist
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
□ Public APIs have docstrings/comments
|
|
376
|
+
□ Parameters and return values documented
|
|
377
|
+
□ Exceptions/errors documented
|
|
378
|
+
□ Usage examples provided
|
|
379
|
+
□ Edge cases and limitations noted
|
|
380
|
+
□ README includes quick start
|
|
381
|
+
□ API reference available
|
|
382
|
+
□ Configuration options documented
|
|
383
|
+
□ Docs are up to date with code
|
|
384
|
+
□ Breaking changes documented
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## Remember
|
|
388
|
+
|
|
389
|
+
- **Code is read more than written** - Good docs save time
|
|
390
|
+
- **Examples speak louder than descriptions** - Show, don't just tell
|
|
391
|
+
- **The best docs are no docs** - Write self-documenting code
|
|
392
|
+
- **Keep it DRY** - Don't repeat what the code already says
|
|
393
|
+
- **Update docs with code** - Outdated docs mislead developers
|