@mytechtoday/augment-extensions 0.1.0 → 0.1.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/AGENTS.md +83 -3
- package/README.md +6 -5
- package/augment-extensions/coding-standards/python/README.md +44 -0
- package/augment-extensions/coding-standards/python/module.json +26 -0
- package/augment-extensions/coding-standards/python/rules/best-practices.md +232 -0
- package/augment-extensions/coding-standards/python/rules/code-organization.md +220 -0
- package/augment-extensions/coding-standards/python/rules/error-handling.md +221 -0
- package/augment-extensions/coding-standards/python/rules/naming-conventions.md +172 -0
- package/augment-extensions/coding-standards/python/rules/type-hints.md +188 -0
- package/augment-extensions/coding-standards/react/README.md +45 -0
- package/augment-extensions/coding-standards/react/module.json +27 -0
- package/augment-extensions/coding-standards/react/rules/component-patterns.md +214 -0
- package/augment-extensions/coding-standards/react/rules/hooks-best-practices.md +235 -0
- package/augment-extensions/coding-standards/react/rules/performance.md +300 -0
- package/augment-extensions/coding-standards/react/rules/state-management.md +265 -0
- package/augment-extensions/coding-standards/react/rules/typescript-react.md +271 -0
- package/augment-extensions/domain-rules/api-design/README.md +41 -0
- package/augment-extensions/domain-rules/api-design/module.json +27 -0
- package/augment-extensions/domain-rules/api-design/rules/authentication.md +263 -0
- package/augment-extensions/domain-rules/api-design/rules/documentation.md +395 -0
- package/augment-extensions/domain-rules/api-design/rules/error-handling.md +290 -0
- package/augment-extensions/domain-rules/api-design/rules/graphql-api.md +313 -0
- package/augment-extensions/domain-rules/api-design/rules/rest-api.md +214 -0
- package/augment-extensions/domain-rules/api-design/rules/versioning.md +268 -0
- package/augment-extensions/domain-rules/security/README.md +41 -0
- package/augment-extensions/domain-rules/security/module.json +28 -0
- package/augment-extensions/domain-rules/security/rules/authentication-security.md +361 -0
- package/augment-extensions/domain-rules/security/rules/encryption.md +208 -0
- package/augment-extensions/domain-rules/security/rules/input-validation.md +294 -0
- package/augment-extensions/domain-rules/security/rules/owasp-top-10.md +339 -0
- package/augment-extensions/domain-rules/security/rules/secure-coding.md +293 -0
- package/augment-extensions/domain-rules/security/rules/web-security.md +268 -0
- package/augment-extensions/examples/design-patterns/README.md +37 -0
- package/augment-extensions/examples/design-patterns/examples/behavioral-patterns.md +370 -0
- package/augment-extensions/examples/design-patterns/examples/creational-patterns.md +250 -0
- package/augment-extensions/examples/design-patterns/examples/structural-patterns.md +264 -0
- package/augment-extensions/examples/design-patterns/module.json +27 -0
- package/{modules → augment-extensions}/workflows/beads/examples/complete-workflow-example.md +5 -5
- package/{modules → augment-extensions}/workflows/beads/rules/file-format.md +45 -1
- package/{modules → augment-extensions}/workflows/beads/rules/workflow.md +41 -0
- package/{modules → augment-extensions}/workflows/openspec/examples/complete-change-example.md +14 -0
- package/{modules → augment-extensions}/workflows/openspec/rules/spec-format.md +44 -1
- package/{modules → augment-extensions}/workflows/openspec/rules/workflow.md +25 -0
- package/cli/dist/cli.js +64 -0
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/coord.d.ts +30 -0
- package/cli/dist/commands/coord.d.ts.map +1 -0
- package/cli/dist/commands/coord.js +150 -0
- package/cli/dist/commands/coord.js.map +1 -0
- package/cli/dist/commands/link.js +1 -1
- package/cli/dist/commands/link.js.map +1 -1
- package/cli/dist/commands/list.js +1 -1
- package/cli/dist/commands/list.js.map +1 -1
- package/cli/dist/commands/search.d.ts.map +1 -1
- package/cli/dist/commands/search.js +107 -5
- package/cli/dist/commands/search.js.map +1 -1
- package/cli/dist/commands/show.js +1 -1
- package/cli/dist/commands/show.js.map +1 -1
- package/cli/dist/commands/sync.d.ts +26 -0
- package/cli/dist/commands/sync.d.ts.map +1 -0
- package/cli/dist/commands/sync.js +106 -0
- package/cli/dist/commands/sync.js.map +1 -0
- package/cli/dist/commands/update.d.ts.map +1 -1
- package/cli/dist/commands/update.js +132 -7
- package/cli/dist/commands/update.js.map +1 -1
- package/cli/dist/utils/auto-sync.d.ts +34 -0
- package/cli/dist/utils/auto-sync.d.ts.map +1 -0
- package/cli/dist/utils/auto-sync.js +172 -0
- package/cli/dist/utils/auto-sync.js.map +1 -0
- package/cli/dist/utils/beads-sync.d.ts +51 -0
- package/cli/dist/utils/beads-sync.d.ts.map +1 -0
- package/cli/dist/utils/beads-sync.js +171 -0
- package/cli/dist/utils/beads-sync.js.map +1 -0
- package/cli/dist/utils/coordination-queries.d.ts +79 -0
- package/cli/dist/utils/coordination-queries.d.ts.map +1 -0
- package/cli/dist/utils/coordination-queries.js +155 -0
- package/cli/dist/utils/coordination-queries.js.map +1 -0
- package/cli/dist/utils/file-tracking.d.ts +42 -0
- package/cli/dist/utils/file-tracking.d.ts.map +1 -0
- package/cli/dist/utils/file-tracking.js +155 -0
- package/cli/dist/utils/file-tracking.js.map +1 -0
- package/cli/dist/utils/migrate.d.ts +25 -0
- package/cli/dist/utils/migrate.d.ts.map +1 -0
- package/cli/dist/utils/migrate.js +204 -0
- package/cli/dist/utils/migrate.js.map +1 -0
- package/cli/dist/utils/openspec-sync.d.ts +48 -0
- package/cli/dist/utils/openspec-sync.d.ts.map +1 -0
- package/cli/dist/utils/openspec-sync.js +167 -0
- package/cli/dist/utils/openspec-sync.js.map +1 -0
- package/{MODULES.md → modules.md} +1 -1
- package/package.json +9 -7
- /package/{modules → augment-extensions}/coding-standards/typescript/README.md +0 -0
- /package/{modules → augment-extensions}/coding-standards/typescript/module.json +0 -0
- /package/{modules → augment-extensions}/coding-standards/typescript/rules/naming-conventions.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/README.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/module.json +0 -0
- /package/{modules → augment-extensions}/workflows/beads/rules/best-practices.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/rules/manual-setup.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/README.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/module.json +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/rules/best-practices.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/rules/manual-setup.md +0 -0
package/AGENTS.md
CHANGED
|
@@ -111,7 +111,7 @@ When making architectural changes:
|
|
|
111
111
|
3. Break down into tasks
|
|
112
112
|
4. Implement and archive when complete
|
|
113
113
|
|
|
114
|
-
**Learn More**: See `
|
|
114
|
+
**Learn More**: See `augment-extensions/workflows/openspec/` for comprehensive workflow documentation.
|
|
115
115
|
|
|
116
116
|
---
|
|
117
117
|
|
|
@@ -137,16 +137,96 @@ This repository uses **Beads** for task tracking and memory.
|
|
|
137
137
|
|
|
138
138
|
When tracking work:
|
|
139
139
|
1. Create tasks by appending JSON to `.beads/issues.jsonl`
|
|
140
|
-
2. Use hash-based IDs
|
|
140
|
+
2. Use hash-based IDs with **"bd-" prefix**: `bd-<hash>` (e.g., `bd-a1b2`)
|
|
141
|
+
- All issue IDs MUST use "bd-" prefix (see `openspec/specs/beads/naming-convention.md`)
|
|
142
|
+
- Valid formats: `bd-<hash>`, `bd-<name>`, `bd-<hash>.<number>`
|
|
141
143
|
3. Track dependencies with `blocks`/`blocked_by` fields
|
|
142
144
|
4. Find ready tasks (status: "open", no blockers)
|
|
143
145
|
5. Update status and add comments as work progresses
|
|
144
146
|
|
|
145
147
|
**Task States**: `open`, `in-progress`, `blocked`, `closed`
|
|
146
148
|
|
|
147
|
-
**
|
|
149
|
+
**Naming Convention**: All issue IDs MUST use "bd-" prefix. See `openspec/specs/beads/naming-convention.md` for complete specification.
|
|
150
|
+
|
|
151
|
+
**Learn More**: See `augment-extensions/workflows/beads/` for comprehensive workflow documentation.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Coordination System
|
|
156
|
+
|
|
157
|
+
This repository uses a **coordination manifest** (`.augment/coordination.json`) to harmonize OpenSpec, Beads, and `.augment/` rules.
|
|
158
|
+
|
|
159
|
+
### How It Works
|
|
160
|
+
|
|
161
|
+
The coordination manifest tracks relationships between:
|
|
162
|
+
- **Specs** (OpenSpec) - What needs to be built
|
|
163
|
+
- **Tasks** (Beads) - How it's being built
|
|
164
|
+
- **Rules** (`.augment/`) - Guidelines for building
|
|
165
|
+
- **Files** - What was built
|
|
166
|
+
|
|
167
|
+
### For AI Agents
|
|
168
|
+
|
|
169
|
+
**Before starting work**:
|
|
170
|
+
1. Check `.augment/coordination.json` for active specs
|
|
171
|
+
2. Find related tasks for the spec you're implementing
|
|
172
|
+
3. Load applicable rules for your task
|
|
173
|
+
4. Identify which files are affected
|
|
174
|
+
|
|
175
|
+
**While working**:
|
|
176
|
+
1. Track file creation/modification with task IDs
|
|
177
|
+
2. Update coordination manifest when creating files
|
|
178
|
+
3. Reference specs and rules in task comments
|
|
179
|
+
|
|
180
|
+
**Query Examples**:
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
// Get all active specs
|
|
184
|
+
const coord = require('./.augment/coordination.json');
|
|
185
|
+
const activeSpecs = Object.entries(coord.specs)
|
|
186
|
+
.filter(([id, spec]) => spec.status === 'active');
|
|
187
|
+
|
|
188
|
+
// Get tasks for a spec
|
|
189
|
+
const tasks = coord.specs['testing/functional-tests'].relatedTasks;
|
|
190
|
+
|
|
191
|
+
// Get rules for a task
|
|
192
|
+
const rules = coord.tasks['bd-xyz'].relatedRules;
|
|
193
|
+
|
|
194
|
+
// Get specs governing a file
|
|
195
|
+
const specsForFile = Object.entries(coord.specs)
|
|
196
|
+
.filter(([id, spec]) =>
|
|
197
|
+
spec.affectedFiles.some(pattern => filePath.match(pattern))
|
|
198
|
+
);
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Learn More**: See `.augment/rules/coordination-system.md` for detailed documentation.
|
|
148
202
|
|
|
149
203
|
---
|
|
150
204
|
|
|
151
205
|
**Note**: This is a meta-repository for extending Augment Code AI. The actual project-specific `.augment/` folder remains in individual projects.
|
|
152
206
|
|
|
207
|
+
|
|
208
|
+
## Landing the Plane (Session Completion)
|
|
209
|
+
|
|
210
|
+
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
|
|
211
|
+
|
|
212
|
+
**MANDATORY WORKFLOW:**
|
|
213
|
+
|
|
214
|
+
1. **File issues for remaining work** - Create issues for anything that needs follow-up
|
|
215
|
+
2. **Run quality gates** (if code changed) - Tests, linters, builds
|
|
216
|
+
3. **Update issue status** - Close finished work, update in-progress items
|
|
217
|
+
4. **PUSH TO REMOTE** - This is MANDATORY:
|
|
218
|
+
```bash
|
|
219
|
+
git pull --rebase
|
|
220
|
+
bd sync
|
|
221
|
+
git push
|
|
222
|
+
git status # MUST show "up to date with origin"
|
|
223
|
+
```
|
|
224
|
+
5. **Clean up** - Clear stashes, prune remote branches
|
|
225
|
+
6. **Verify** - All changes committed AND pushed
|
|
226
|
+
7. **Hand off** - Provide context for next session
|
|
227
|
+
|
|
228
|
+
**CRITICAL RULES:**
|
|
229
|
+
- Work is NOT complete until `git push` succeeds
|
|
230
|
+
- NEVER stop before pushing - that leaves work stranded locally
|
|
231
|
+
- NEVER say "ready to push when you are" - YOU must push
|
|
232
|
+
- If push fails, resolve and retry until it succeeds
|
package/README.md
CHANGED
|
@@ -20,14 +20,15 @@ Augment Code AI limits the `.augment/` folder to ~49,400 characters. This reposi
|
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
# Install the CLI
|
|
23
|
-
npm install -g @augment-extensions
|
|
23
|
+
npm install -g @mytechtoday/augment-extensions
|
|
24
24
|
|
|
25
25
|
# Initialize in your project
|
|
26
26
|
augx init
|
|
27
27
|
|
|
28
28
|
# Link extension modules
|
|
29
29
|
augx link coding-standards/typescript
|
|
30
|
-
augx link domain-rules/
|
|
30
|
+
augx link domain-rules/api-design
|
|
31
|
+
augx link domain-rules/security
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
### For AI Agents
|
|
@@ -41,7 +42,7 @@ Once initialized, AI agents automatically discover available extensions through:
|
|
|
41
42
|
|
|
42
43
|
```
|
|
43
44
|
augment-extensions/
|
|
44
|
-
├──
|
|
45
|
+
├── augment-extensions/ # Extension modules
|
|
45
46
|
│ ├── coding-standards/ # Language/framework standards
|
|
46
47
|
│ │ ├── typescript/
|
|
47
48
|
│ │ ├── python/
|
|
@@ -68,7 +69,7 @@ augment-extensions/
|
|
|
68
69
|
Each module is self-contained:
|
|
69
70
|
|
|
70
71
|
```
|
|
71
|
-
|
|
72
|
+
augment-extensions/coding-standards/typescript/
|
|
72
73
|
├── module.json # Metadata (version, dependencies)
|
|
73
74
|
├── rules/ # Rule files
|
|
74
75
|
│ ├── naming-conventions.md
|
|
@@ -112,7 +113,7 @@ augx pin typescript-standards@1.2.0
|
|
|
112
113
|
|
|
113
114
|
## 📖 Available Modules
|
|
114
115
|
|
|
115
|
-
See [
|
|
116
|
+
See [modules.md](./modules.md) for a complete catalog of available extension modules.
|
|
116
117
|
|
|
117
118
|
## 🛠 Creating Custom Modules
|
|
118
119
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Python Coding Standards
|
|
2
|
+
|
|
3
|
+
Comprehensive Python coding standards and best practices for AI-assisted development.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This module provides detailed guidelines for writing clean, maintainable, and Pythonic code following PEP 8 and modern Python best practices.
|
|
8
|
+
|
|
9
|
+
## Key Benefits
|
|
10
|
+
|
|
11
|
+
- **Type Safety**: Comprehensive type hints usage
|
|
12
|
+
- **Error Handling**: Proper exception handling patterns
|
|
13
|
+
- **Code Quality**: PEP 8 compliance and best practices
|
|
14
|
+
- **Modern Python**: Python 3.10+ features and patterns
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
augx link coding-standards/python
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Contents
|
|
23
|
+
|
|
24
|
+
### Rules
|
|
25
|
+
|
|
26
|
+
- **naming-conventions.md** - PEP 8 naming standards
|
|
27
|
+
- **type-hints.md** - Type hints and type checking
|
|
28
|
+
- **error-handling.md** - Exception handling patterns
|
|
29
|
+
- **best-practices.md** - General Python best practices
|
|
30
|
+
- **code-organization.md** - Module and package structure
|
|
31
|
+
|
|
32
|
+
### Examples
|
|
33
|
+
|
|
34
|
+
- **type-hints-examples.md** - Type hints usage examples
|
|
35
|
+
- **error-handling-examples.md** - Exception handling examples
|
|
36
|
+
|
|
37
|
+
## Character Count
|
|
38
|
+
|
|
39
|
+
~28,500 characters
|
|
40
|
+
|
|
41
|
+
## Version
|
|
42
|
+
|
|
43
|
+
1.0.0
|
|
44
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "python-standards",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"displayName": "Python Coding Standards",
|
|
5
|
+
"description": "Comprehensive Python coding standards including naming conventions, type hints, and error handling",
|
|
6
|
+
"type": "coding-standards",
|
|
7
|
+
"author": "Augment Extensions",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"augment": {
|
|
10
|
+
"characterCount": 28500,
|
|
11
|
+
"priority": "medium",
|
|
12
|
+
"category": "coding-standards"
|
|
13
|
+
},
|
|
14
|
+
"installation": {
|
|
15
|
+
"required": false,
|
|
16
|
+
"dependencies": []
|
|
17
|
+
},
|
|
18
|
+
"tags": [
|
|
19
|
+
"python",
|
|
20
|
+
"pep8",
|
|
21
|
+
"type-hints",
|
|
22
|
+
"error-handling",
|
|
23
|
+
"best-practices"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# Python Best Practices
|
|
2
|
+
|
|
3
|
+
General Python best practices for clean, maintainable code.
|
|
4
|
+
|
|
5
|
+
## Code Style
|
|
6
|
+
|
|
7
|
+
Follow PEP 8 strictly. Use tools like `black`, `flake8`, and `isort`.
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
# Good - PEP 8 compliant
|
|
11
|
+
def calculate_total_price(items: List[Item], tax_rate: float = 0.1) -> float:
|
|
12
|
+
"""Calculate total price including tax."""
|
|
13
|
+
subtotal = sum(item.price for item in items)
|
|
14
|
+
return subtotal * (1 + tax_rate)
|
|
15
|
+
|
|
16
|
+
# Bad - Not PEP 8 compliant
|
|
17
|
+
def calculateTotalPrice(items,tax_rate=0.1):
|
|
18
|
+
subtotal=sum([item.price for item in items])
|
|
19
|
+
return subtotal*(1+tax_rate)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## List Comprehensions
|
|
23
|
+
|
|
24
|
+
Use comprehensions for simple transformations, loops for complex logic.
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
# Good - Simple transformation
|
|
28
|
+
squares = [x**2 for x in range(10)]
|
|
29
|
+
even_squares = [x**2 for x in range(10) if x % 2 == 0]
|
|
30
|
+
|
|
31
|
+
# Good - Dictionary comprehension
|
|
32
|
+
user_ages = {user.name: user.age for user in users}
|
|
33
|
+
|
|
34
|
+
# Bad - Too complex
|
|
35
|
+
result = [
|
|
36
|
+
process_item(item, config)
|
|
37
|
+
for item in items
|
|
38
|
+
if item.is_valid() and item.status == 'active'
|
|
39
|
+
for config in get_configs(item)
|
|
40
|
+
if config.enabled
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
# Better - Use regular loop for complex logic
|
|
44
|
+
result = []
|
|
45
|
+
for item in items:
|
|
46
|
+
if item.is_valid() and item.status == 'active':
|
|
47
|
+
for config in get_configs(item):
|
|
48
|
+
if config.enabled:
|
|
49
|
+
result.append(process_item(item, config))
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Function Design
|
|
53
|
+
|
|
54
|
+
Keep functions small, focused, and testable.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
# Good - Single responsibility
|
|
58
|
+
def validate_email(email: str) -> bool:
|
|
59
|
+
"""Validate email format."""
|
|
60
|
+
return '@' in email and '.' in email.split('@')[1]
|
|
61
|
+
|
|
62
|
+
def send_email(to: str, subject: str, body: str) -> None:
|
|
63
|
+
"""Send email to recipient."""
|
|
64
|
+
if not validate_email(to):
|
|
65
|
+
raise ValueError(f"Invalid email: {to}")
|
|
66
|
+
# Send email logic
|
|
67
|
+
|
|
68
|
+
# Bad - Multiple responsibilities
|
|
69
|
+
def send_email(to: str, subject: str, body: str) -> None:
|
|
70
|
+
# Validation
|
|
71
|
+
if '@' not in to or '.' not in to.split('@')[1]:
|
|
72
|
+
raise ValueError(f"Invalid email: {to}")
|
|
73
|
+
# Database logging
|
|
74
|
+
db.log_email(to, subject)
|
|
75
|
+
# Sending
|
|
76
|
+
smtp.send(to, subject, body)
|
|
77
|
+
# Analytics
|
|
78
|
+
analytics.track('email_sent', to)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Use Dataclasses
|
|
82
|
+
|
|
83
|
+
For simple data containers, use dataclasses instead of regular classes.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from dataclasses import dataclass, field
|
|
87
|
+
from typing import List
|
|
88
|
+
|
|
89
|
+
# Good - Dataclass
|
|
90
|
+
@dataclass
|
|
91
|
+
class User:
|
|
92
|
+
name: str
|
|
93
|
+
email: str
|
|
94
|
+
age: int
|
|
95
|
+
tags: List[str] = field(default_factory=list)
|
|
96
|
+
|
|
97
|
+
def is_adult(self) -> bool:
|
|
98
|
+
return self.age >= 18
|
|
99
|
+
|
|
100
|
+
# Bad - Manual implementation
|
|
101
|
+
class User:
|
|
102
|
+
def __init__(self, name, email, age, tags=None):
|
|
103
|
+
self.name = name
|
|
104
|
+
self.email = email
|
|
105
|
+
self.age = age
|
|
106
|
+
self.tags = tags if tags is not None else []
|
|
107
|
+
|
|
108
|
+
def __repr__(self):
|
|
109
|
+
return f"User(name={self.name}, email={self.email}, age={self.age})"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Use Enums
|
|
113
|
+
|
|
114
|
+
For fixed sets of values, use Enums.
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from enum import Enum, auto
|
|
118
|
+
|
|
119
|
+
# Good - Enum
|
|
120
|
+
class Status(Enum):
|
|
121
|
+
PENDING = auto()
|
|
122
|
+
APPROVED = auto()
|
|
123
|
+
REJECTED = auto()
|
|
124
|
+
|
|
125
|
+
def process_request(status: Status) -> None:
|
|
126
|
+
if status == Status.APPROVED:
|
|
127
|
+
approve()
|
|
128
|
+
elif status == Status.REJECTED:
|
|
129
|
+
reject()
|
|
130
|
+
|
|
131
|
+
# Bad - String constants
|
|
132
|
+
STATUS_PENDING = "pending"
|
|
133
|
+
STATUS_APPROVED = "approved"
|
|
134
|
+
STATUS_REJECTED = "rejected"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Use Pathlib
|
|
138
|
+
|
|
139
|
+
For file paths, use `pathlib` instead of string manipulation.
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from pathlib import Path
|
|
143
|
+
|
|
144
|
+
# Good - Pathlib
|
|
145
|
+
config_dir = Path.home() / '.config' / 'myapp'
|
|
146
|
+
config_file = config_dir / 'config.json'
|
|
147
|
+
|
|
148
|
+
if config_file.exists():
|
|
149
|
+
data = config_file.read_text()
|
|
150
|
+
|
|
151
|
+
# Bad - String manipulation
|
|
152
|
+
import os
|
|
153
|
+
config_dir = os.path.join(os.path.expanduser('~'), '.config', 'myapp')
|
|
154
|
+
config_file = os.path.join(config_dir, 'config.json')
|
|
155
|
+
|
|
156
|
+
if os.path.exists(config_file):
|
|
157
|
+
with open(config_file) as f:
|
|
158
|
+
data = f.read()
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Use F-Strings
|
|
162
|
+
|
|
163
|
+
For string formatting, use f-strings (Python 3.6+).
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
# Good - F-strings
|
|
167
|
+
name = "Alice"
|
|
168
|
+
age = 30
|
|
169
|
+
message = f"Hello, {name}! You are {age} years old."
|
|
170
|
+
formatted = f"Price: ${price:.2f}"
|
|
171
|
+
|
|
172
|
+
# Bad - Old-style formatting
|
|
173
|
+
message = "Hello, %s! You are %d years old." % (name, age)
|
|
174
|
+
message = "Hello, {}! You are {} years old.".format(name, age)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Use Generators
|
|
178
|
+
|
|
179
|
+
For large datasets, use generators to save memory.
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
# Good - Generator
|
|
183
|
+
def read_large_file(file_path: Path):
|
|
184
|
+
with file_path.open() as f:
|
|
185
|
+
for line in f:
|
|
186
|
+
yield line.strip()
|
|
187
|
+
|
|
188
|
+
# Usage
|
|
189
|
+
for line in read_large_file(Path('large_file.txt')):
|
|
190
|
+
process(line)
|
|
191
|
+
|
|
192
|
+
# Bad - Load everything into memory
|
|
193
|
+
def read_large_file(file_path: Path):
|
|
194
|
+
with file_path.open() as f:
|
|
195
|
+
return [line.strip() for line in f]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Use Default Dict and Counter
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
from collections import defaultdict, Counter
|
|
202
|
+
|
|
203
|
+
# Good - defaultdict
|
|
204
|
+
word_count = defaultdict(int)
|
|
205
|
+
for word in words:
|
|
206
|
+
word_count[word] += 1
|
|
207
|
+
|
|
208
|
+
# Good - Counter (even better)
|
|
209
|
+
word_count = Counter(words)
|
|
210
|
+
|
|
211
|
+
# Bad - Manual checking
|
|
212
|
+
word_count = {}
|
|
213
|
+
for word in words:
|
|
214
|
+
if word in word_count:
|
|
215
|
+
word_count[word] += 1
|
|
216
|
+
else:
|
|
217
|
+
word_count[word] = 1
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Best Practices Summary
|
|
221
|
+
|
|
222
|
+
1. **Follow PEP 8** - Use automated formatters
|
|
223
|
+
2. **Use type hints** - Everywhere
|
|
224
|
+
3. **Keep functions small** - Single responsibility
|
|
225
|
+
4. **Use dataclasses** - For data containers
|
|
226
|
+
5. **Use Enums** - For fixed sets of values
|
|
227
|
+
6. **Use pathlib** - For file paths
|
|
228
|
+
7. **Use f-strings** - For string formatting
|
|
229
|
+
8. **Use generators** - For large datasets
|
|
230
|
+
9. **Use comprehensions** - For simple transformations
|
|
231
|
+
10. **Write tests** - Always
|
|
232
|
+
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Python Code Organization
|
|
2
|
+
|
|
3
|
+
Best practices for organizing Python modules, packages, and projects.
|
|
4
|
+
|
|
5
|
+
## Module Structure
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
"""Module docstring describing the module's purpose.
|
|
9
|
+
|
|
10
|
+
This module provides utilities for user authentication.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# Standard library imports
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import List, Dict, Optional
|
|
18
|
+
|
|
19
|
+
# Third-party imports
|
|
20
|
+
import requests
|
|
21
|
+
from flask import Flask, request
|
|
22
|
+
|
|
23
|
+
# Local imports
|
|
24
|
+
from .models import User
|
|
25
|
+
from .utils import validate_email
|
|
26
|
+
from ..config import settings
|
|
27
|
+
|
|
28
|
+
# Constants
|
|
29
|
+
MAX_LOGIN_ATTEMPTS = 3
|
|
30
|
+
DEFAULT_TIMEOUT = 30
|
|
31
|
+
|
|
32
|
+
# Module-level variables
|
|
33
|
+
_cache: Dict[str, User] = {}
|
|
34
|
+
|
|
35
|
+
# Classes
|
|
36
|
+
class AuthenticationManager:
|
|
37
|
+
"""Manages user authentication."""
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
# Functions
|
|
41
|
+
def authenticate_user(username: str, password: str) -> Optional[User]:
|
|
42
|
+
"""Authenticate user with username and password."""
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
# Main execution
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
main()
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Package Structure
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
myproject/
|
|
54
|
+
├── README.md
|
|
55
|
+
├── pyproject.toml
|
|
56
|
+
├── setup.py
|
|
57
|
+
├── requirements.txt
|
|
58
|
+
├── .gitignore
|
|
59
|
+
├── tests/
|
|
60
|
+
│ ├── __init__.py
|
|
61
|
+
│ ├── test_auth.py
|
|
62
|
+
│ └── test_users.py
|
|
63
|
+
└── myproject/
|
|
64
|
+
├── __init__.py
|
|
65
|
+
├── __main__.py
|
|
66
|
+
├── config.py
|
|
67
|
+
├── models/
|
|
68
|
+
│ ├── __init__.py
|
|
69
|
+
│ ├── user.py
|
|
70
|
+
│ └── product.py
|
|
71
|
+
├── services/
|
|
72
|
+
│ ├── __init__.py
|
|
73
|
+
│ ├── auth.py
|
|
74
|
+
│ └── email.py
|
|
75
|
+
└── utils/
|
|
76
|
+
├── __init__.py
|
|
77
|
+
├── validation.py
|
|
78
|
+
└── formatting.py
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Import Organization
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
# 1. Standard library imports (alphabetical)
|
|
85
|
+
import json
|
|
86
|
+
import os
|
|
87
|
+
import sys
|
|
88
|
+
from datetime import datetime
|
|
89
|
+
from pathlib import Path
|
|
90
|
+
from typing import List, Dict, Optional
|
|
91
|
+
|
|
92
|
+
# 2. Third-party imports (alphabetical)
|
|
93
|
+
import numpy as np
|
|
94
|
+
import pandas as pd
|
|
95
|
+
import requests
|
|
96
|
+
from flask import Flask, request, jsonify
|
|
97
|
+
|
|
98
|
+
# 3. Local application imports (alphabetical)
|
|
99
|
+
from .config import settings
|
|
100
|
+
from .models import User, Product
|
|
101
|
+
from .services import AuthService, EmailService
|
|
102
|
+
from .utils import validate_email, format_date
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## __init__.py Files
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
# myproject/__init__.py
|
|
109
|
+
"""MyProject - A Python application."""
|
|
110
|
+
|
|
111
|
+
__version__ = "1.0.0"
|
|
112
|
+
__author__ = "Your Name"
|
|
113
|
+
|
|
114
|
+
# Public API
|
|
115
|
+
from .models import User, Product
|
|
116
|
+
from .services import AuthService, EmailService
|
|
117
|
+
|
|
118
|
+
__all__ = [
|
|
119
|
+
"User",
|
|
120
|
+
"Product",
|
|
121
|
+
"AuthService",
|
|
122
|
+
"EmailService",
|
|
123
|
+
]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Configuration Management
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
# config.py
|
|
130
|
+
from pathlib import Path
|
|
131
|
+
from typing import Optional
|
|
132
|
+
from pydantic import BaseSettings
|
|
133
|
+
|
|
134
|
+
class Settings(BaseSettings):
|
|
135
|
+
"""Application settings."""
|
|
136
|
+
|
|
137
|
+
# App settings
|
|
138
|
+
app_name: str = "MyApp"
|
|
139
|
+
debug: bool = False
|
|
140
|
+
|
|
141
|
+
# Database settings
|
|
142
|
+
database_url: str
|
|
143
|
+
database_pool_size: int = 10
|
|
144
|
+
|
|
145
|
+
# API settings
|
|
146
|
+
api_key: Optional[str] = None
|
|
147
|
+
api_timeout: int = 30
|
|
148
|
+
|
|
149
|
+
class Config:
|
|
150
|
+
env_file = ".env"
|
|
151
|
+
env_file_encoding = "utf-8"
|
|
152
|
+
|
|
153
|
+
# Global settings instance
|
|
154
|
+
settings = Settings()
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Dependency Injection
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
# Good - Dependency injection
|
|
161
|
+
class UserService:
|
|
162
|
+
def __init__(self, db_connection, email_service):
|
|
163
|
+
self.db = db_connection
|
|
164
|
+
self.email = email_service
|
|
165
|
+
|
|
166
|
+
def create_user(self, user_data):
|
|
167
|
+
user = self.db.create(user_data)
|
|
168
|
+
self.email.send_welcome(user.email)
|
|
169
|
+
return user
|
|
170
|
+
|
|
171
|
+
# Usage
|
|
172
|
+
db = DatabaseConnection(settings.database_url)
|
|
173
|
+
email = EmailService(settings.smtp_config)
|
|
174
|
+
user_service = UserService(db, email)
|
|
175
|
+
|
|
176
|
+
# Bad - Hard-coded dependencies
|
|
177
|
+
class UserService:
|
|
178
|
+
def __init__(self):
|
|
179
|
+
self.db = DatabaseConnection("postgresql://...")
|
|
180
|
+
self.email = EmailService(smtp_config)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Layered Architecture
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
myproject/
|
|
187
|
+
├── api/ # API layer (Flask/FastAPI routes)
|
|
188
|
+
│ ├── __init__.py
|
|
189
|
+
│ ├── users.py
|
|
190
|
+
│ └── products.py
|
|
191
|
+
├── services/ # Business logic layer
|
|
192
|
+
│ ├── __init__.py
|
|
193
|
+
│ ├── user_service.py
|
|
194
|
+
│ └── product_service.py
|
|
195
|
+
├── repositories/ # Data access layer
|
|
196
|
+
│ ├── __init__.py
|
|
197
|
+
│ ├── user_repository.py
|
|
198
|
+
│ └── product_repository.py
|
|
199
|
+
├── models/ # Domain models
|
|
200
|
+
│ ├── __init__.py
|
|
201
|
+
│ ├── user.py
|
|
202
|
+
│ └── product.py
|
|
203
|
+
└── utils/ # Utilities
|
|
204
|
+
├── __init__.py
|
|
205
|
+
└── validators.py
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Best Practices
|
|
209
|
+
|
|
210
|
+
1. **One class per file** - For large classes
|
|
211
|
+
2. **Group related functions** - In modules
|
|
212
|
+
3. **Use __all__** - To define public API
|
|
213
|
+
4. **Avoid circular imports** - Restructure if needed
|
|
214
|
+
5. **Use absolute imports** - For clarity
|
|
215
|
+
6. **Keep modules focused** - Single responsibility
|
|
216
|
+
7. **Use packages** - For large projects
|
|
217
|
+
8. **Document structure** - In README.md
|
|
218
|
+
9. **Follow conventions** - tests/, docs/, src/
|
|
219
|
+
10. **Use pyproject.toml** - For modern projects
|
|
220
|
+
|