metacoding 1.0.0 → 1.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/CHANGELOG.md +79 -42
- package/LICENSE +1 -1
- package/lib/commands/init.d.ts.map +1 -1
- package/lib/commands/init.js +1 -1
- package/lib/commands/init.js.map +1 -1
- package/lib/services/template-manager.d.ts +4 -1
- package/lib/services/template-manager.d.ts.map +1 -1
- package/lib/services/template-manager.js +129 -10
- package/lib/services/template-manager.js.map +1 -1
- package/lib/services/vscode.js +1 -1
- package/lib/services/vscode.js.map +1 -1
- package/package.json +12 -4
- package/templates/general/code-review.instructions.md +265 -0
- package/templates/general/{files/copilot-instructions.md.template → copilot-instructions.md} +97 -140
- package/templates/{python/files → general}/docs-update.instructions.md +45 -32
- package/templates/general/release.instructions.md +242 -0
- package/templates/general/test-runner.instructions.md +188 -0
- package/templates/node/nodejs.coding.instructions.md +249 -0
- package/templates/node/nodejs.docs.instructions.md +234 -0
- package/templates/node/nodejs.testing.instructions.md +373 -0
- package/templates/python/python.coding.instructions.md +339 -0
- package/templates/python/python.docs.instructions.md +1147 -0
- package/templates/python/python.testing.instructions.md +1074 -0
- package/templates/react/react.coding.instructions.md +695 -0
- package/templates/react/react.docs.instructions.md +427 -0
- package/templates/react/react.testing.instructions.md +193 -0
- package/templates/react/test-runner.instructions.md +135 -0
- package/templates/typescript/template.json +16 -0
- package/templates/typescript/typescript.coding.instructions.md +368 -0
- package/templates/typescript/typescript.docs.instructions.md +734 -0
- package/templates/typescript/typescript.testing.instructions.md +740 -0
- package/templates/general/files/code-review.instructions.md +0 -111
- package/templates/general/files/docs-update.instructions.md +0 -203
- package/templates/general/files/release.instructions.md +0 -72
- package/templates/general/files/test-runner.instructions.md +0 -107
- package/templates/node/files/code-review.instructions.md +0 -222
- package/templates/node/files/copilot-instructions.md.template +0 -391
- package/templates/node/files/docs-update.instructions.md +0 -203
- package/templates/node/files/release.instructions.md +0 -72
- package/templates/node/files/test-runner.instructions.md +0 -108
- package/templates/python/files/code-review.instructions.md +0 -215
- package/templates/python/files/copilot-instructions.md.template +0 -418
- package/templates/python/files/release.instructions.md +0 -72
- package/templates/python/files/test-runner.instructions.md +0 -108
- package/templates/react/files/code-review.instructions.md +0 -160
- package/templates/react/files/copilot-instructions.md.template +0 -472
- package/templates/react/files/docs-update.instructions.md +0 -203
- package/templates/react/files/release.instructions.md +0 -72
- package/templates/react/files/test-runner.instructions.md +0 -108
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 'Node.js backend testing strategies and frameworks'
|
|
3
|
+
applyTo: 'test/**/*.{ts,js}'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Node.js Backend Testing Guidelines
|
|
7
|
+
|
|
8
|
+
## Test Case Naming Conventions
|
|
9
|
+
|
|
10
|
+
### Test Case ID Format: `[AREA]-[TYPE]-[NUMBER]`
|
|
11
|
+
|
|
12
|
+
**Node.js/Backend Area Prefixes:**
|
|
13
|
+
|
|
14
|
+
- `API` - REST API endpoint tests
|
|
15
|
+
- `SRV` - Service layer tests
|
|
16
|
+
- `DB` - Database/ORM tests
|
|
17
|
+
- `AUTH` - Authentication/Authorization tests
|
|
18
|
+
- `UTIL` - Backend utility function tests
|
|
19
|
+
- `CONFIG` - Configuration management tests
|
|
20
|
+
- `MIDDLEWARE` - Express middleware tests
|
|
21
|
+
- `QUEUE` - Message queue/job processing tests
|
|
22
|
+
- `CACHE` - Caching layer tests
|
|
23
|
+
- `VALIDATION` - Input validation tests
|
|
24
|
+
|
|
25
|
+
**Type Suffixes:**
|
|
26
|
+
|
|
27
|
+
- `UNIT` - Unit tests (isolated component testing)
|
|
28
|
+
- `INT` - Integration tests (component interaction testing)
|
|
29
|
+
- `E2E` - End-to-end tests (full API workflow testing)
|
|
30
|
+
|
|
31
|
+
**Examples:**
|
|
32
|
+
|
|
33
|
+
- `API-UNIT-001` - First unit test for API endpoint
|
|
34
|
+
- `SRV-UNIT-001` - First unit test for Service layer
|
|
35
|
+
- `DB-INT-001` - First integration test for Database layer
|
|
36
|
+
- `AUTH-E2E-001` - First end-to-end authentication test
|
|
37
|
+
|
|
38
|
+
## Testing Strategy Overview
|
|
39
|
+
|
|
40
|
+
### Testing Pyramid for Node.js Backend
|
|
41
|
+
|
|
42
|
+
- **Unit Tests (70%):** Test individual functions and modules in isolation
|
|
43
|
+
- **Integration Tests (20%):** Test interactions between components
|
|
44
|
+
- **End-to-End Tests (10%):** Test complete user workflows through APIs
|
|
45
|
+
- **Contract Tests:** Verify API contracts and external service interactions
|
|
46
|
+
|
|
47
|
+
### Test Framework Selection
|
|
48
|
+
|
|
49
|
+
- **Primary Framework:** Jest for unit and integration testing
|
|
50
|
+
- **API Testing:** Supertest for HTTP endpoint testing
|
|
51
|
+
- **Database Testing:** Test containers or in-memory databases
|
|
52
|
+
- **Mocking:** Jest mocks for external dependencies
|
|
53
|
+
- **Load Testing:** Artillery or k6 for performance testing
|
|
54
|
+
|
|
55
|
+
## Unit Testing Best Practices
|
|
56
|
+
|
|
57
|
+
### Test Structure and Organization
|
|
58
|
+
|
|
59
|
+
- **Test File Naming:** Use `.test.ts` or `.spec.ts` suffix
|
|
60
|
+
- **Test Grouping:** Group related tests using `describe` blocks
|
|
61
|
+
- **Test Isolation:** Each test should be independent and idempotent
|
|
62
|
+
- **Test Data:** Use factories or builders for test data creation
|
|
63
|
+
- **Test Cleanup:** Clean up resources after each test
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// Example test structure
|
|
67
|
+
describe('UserService', () => {
|
|
68
|
+
let userService: UserService;
|
|
69
|
+
let mockRepository: jest.Mocked<UserRepository>;
|
|
70
|
+
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
mockRepository = createMockRepository();
|
|
73
|
+
userService = new UserService(mockRepository);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('createUser', () => {
|
|
77
|
+
it('should create a user with valid data', async () => {
|
|
78
|
+
// Arrange
|
|
79
|
+
const userData = UserFactory.build();
|
|
80
|
+
mockRepository.save.mockResolvedValue(userData);
|
|
81
|
+
|
|
82
|
+
// Act
|
|
83
|
+
const result = await userService.createUser(userData);
|
|
84
|
+
|
|
85
|
+
// Assert
|
|
86
|
+
expect(result).toEqual(userData);
|
|
87
|
+
expect(mockRepository.save).toHaveBeenCalledWith(userData);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should throw ValidationError for invalid email', async () => {
|
|
91
|
+
// Arrange
|
|
92
|
+
const invalidUserData = UserFactory.build({ email: 'invalid-email' });
|
|
93
|
+
|
|
94
|
+
// Act & Assert
|
|
95
|
+
await expect(userService.createUser(invalidUserData)).rejects.toThrow(
|
|
96
|
+
ValidationError
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Mocking Strategies
|
|
104
|
+
|
|
105
|
+
- **External Dependencies:** Mock all external services and databases
|
|
106
|
+
- **File System Operations:** Mock file system interactions
|
|
107
|
+
- **Time-Dependent Code:** Mock dates and timers
|
|
108
|
+
- **Environment Variables:** Mock configuration and environment
|
|
109
|
+
- **HTTP Requests:** Mock external API calls
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// Example mocking patterns
|
|
113
|
+
jest.mock('fs-extra');
|
|
114
|
+
jest.mock('../services/email-service');
|
|
115
|
+
|
|
116
|
+
const mockFs = fs as jest.Mocked<typeof fs>;
|
|
117
|
+
const mockEmailService = EmailService as jest.MockedClass<typeof EmailService>;
|
|
118
|
+
|
|
119
|
+
describe('FileProcessor', () => {
|
|
120
|
+
beforeEach(() => {
|
|
121
|
+
jest.clearAllMocks();
|
|
122
|
+
mockFs.readFile.mockResolvedValue('file content');
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Integration Testing
|
|
128
|
+
|
|
129
|
+
### Database Testing
|
|
130
|
+
|
|
131
|
+
- **Test Database:** Use separate test database or test containers
|
|
132
|
+
- **Transaction Rollback:** Rollback transactions after each test
|
|
133
|
+
- **Seed Data:** Create consistent test data sets
|
|
134
|
+
- **Migration Testing:** Test database migrations
|
|
135
|
+
- **Performance Testing:** Test query performance
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Example database integration test
|
|
139
|
+
describe('UserRepository Integration', () => {
|
|
140
|
+
let repository: UserRepository;
|
|
141
|
+
let connection: Connection;
|
|
142
|
+
|
|
143
|
+
beforeAll(async () => {
|
|
144
|
+
connection = await createTestConnection();
|
|
145
|
+
repository = new UserRepository(connection);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
afterAll(async () => {
|
|
149
|
+
await connection.close();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
beforeEach(async () => {
|
|
153
|
+
await connection.synchronize(true); // Reset database
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should save and retrieve user correctly', async () => {
|
|
157
|
+
// Arrange
|
|
158
|
+
const userData = UserFactory.build();
|
|
159
|
+
|
|
160
|
+
// Act
|
|
161
|
+
const savedUser = await repository.save(userData);
|
|
162
|
+
const retrievedUser = await repository.findById(savedUser.id);
|
|
163
|
+
|
|
164
|
+
// Assert
|
|
165
|
+
expect(retrievedUser).toEqual(savedUser);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### API Endpoint Testing
|
|
171
|
+
|
|
172
|
+
- **HTTP Testing:** Use Supertest for endpoint testing
|
|
173
|
+
- **Authentication Testing:** Test auth middleware and permissions
|
|
174
|
+
- **Validation Testing:** Test request validation and error responses
|
|
175
|
+
- **Response Format:** Verify response structure and data types
|
|
176
|
+
- **Status Code Testing:** Test all possible HTTP status codes
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// Example API endpoint test
|
|
180
|
+
describe('POST /api/v1/users', () => {
|
|
181
|
+
let app: Application;
|
|
182
|
+
|
|
183
|
+
beforeAll(() => {
|
|
184
|
+
app = createTestApp();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should create user with valid data', async () => {
|
|
188
|
+
// Arrange
|
|
189
|
+
const userData = UserFactory.build();
|
|
190
|
+
|
|
191
|
+
// Act
|
|
192
|
+
const response = await request(app)
|
|
193
|
+
.post('/api/v1/users')
|
|
194
|
+
.send(userData)
|
|
195
|
+
.expect(201);
|
|
196
|
+
|
|
197
|
+
// Assert
|
|
198
|
+
expect(response.body.success).toBe(true);
|
|
199
|
+
expect(response.body.data.email).toBe(userData.email);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('should return 400 for invalid email', async () => {
|
|
203
|
+
// Arrange
|
|
204
|
+
const invalidData = UserFactory.build({ email: 'invalid' });
|
|
205
|
+
|
|
206
|
+
// Act
|
|
207
|
+
const response = await request(app)
|
|
208
|
+
.post('/api/v1/users')
|
|
209
|
+
.send(invalidData)
|
|
210
|
+
.expect(400);
|
|
211
|
+
|
|
212
|
+
// Assert
|
|
213
|
+
expect(response.body.success).toBe(false);
|
|
214
|
+
expect(response.body.error.code).toBe('VALIDATION_ERROR');
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## End-to-End Testing
|
|
220
|
+
|
|
221
|
+
### Full Workflow Testing
|
|
222
|
+
|
|
223
|
+
- **User Scenarios:** Test complete user journeys
|
|
224
|
+
- **Multi-Service Testing:** Test interactions between services
|
|
225
|
+
- **Real Database:** Use real database for E2E tests
|
|
226
|
+
- **External Services:** Use real or staging external services
|
|
227
|
+
- **Browser Testing:** Test web interfaces if applicable
|
|
228
|
+
|
|
229
|
+
### Authentication and Authorization Testing
|
|
230
|
+
|
|
231
|
+
- **Login Flows:** Test complete authentication flows
|
|
232
|
+
- **Token Management:** Test token generation and validation
|
|
233
|
+
- **Permission Testing:** Test role-based access control
|
|
234
|
+
- **Session Management:** Test session creation and cleanup
|
|
235
|
+
- **Security Testing:** Test for common security vulnerabilities
|
|
236
|
+
|
|
237
|
+
## Performance Testing
|
|
238
|
+
|
|
239
|
+
### Load Testing Strategies
|
|
240
|
+
|
|
241
|
+
- **Baseline Performance:** Establish performance baselines
|
|
242
|
+
- **Stress Testing:** Test system limits and breaking points
|
|
243
|
+
- **Spike Testing:** Test sudden load increases
|
|
244
|
+
- **Volume Testing:** Test with large amounts of data
|
|
245
|
+
- **Endurance Testing:** Test sustained load over time
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
// Example Artillery load test configuration
|
|
249
|
+
config:
|
|
250
|
+
target: 'http://localhost:3000'
|
|
251
|
+
phases:
|
|
252
|
+
- duration: 60
|
|
253
|
+
arrivalRate: 10
|
|
254
|
+
- duration: 120
|
|
255
|
+
arrivalRate: 50
|
|
256
|
+
- duration: 60
|
|
257
|
+
arrivalRate: 10
|
|
258
|
+
|
|
259
|
+
scenarios:
|
|
260
|
+
- name: 'User Creation Flow'
|
|
261
|
+
weight: 70
|
|
262
|
+
flow:
|
|
263
|
+
- post:
|
|
264
|
+
url: '/api/v1/users'
|
|
265
|
+
json:
|
|
266
|
+
email: '{{ $randomEmail() }}'
|
|
267
|
+
name: '{{ $randomString() }}'
|
|
268
|
+
- think: 1
|
|
269
|
+
|
|
270
|
+
- name: 'User Retrieval'
|
|
271
|
+
weight: 30
|
|
272
|
+
flow:
|
|
273
|
+
- get:
|
|
274
|
+
url: '/api/v1/users/{{ userId }}'
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Database Performance Testing
|
|
278
|
+
|
|
279
|
+
- **Query Performance:** Test slow query detection
|
|
280
|
+
- **Connection Pool Testing:** Test connection pool limits
|
|
281
|
+
- **Transaction Performance:** Test transaction overhead
|
|
282
|
+
- **Index Effectiveness:** Test query optimization
|
|
283
|
+
- **Data Volume Testing:** Test with production-like data volumes
|
|
284
|
+
|
|
285
|
+
## Test Data Management
|
|
286
|
+
|
|
287
|
+
### Test Factories and Builders
|
|
288
|
+
|
|
289
|
+
- **Data Factories:** Create consistent test data
|
|
290
|
+
- **Builder Pattern:** Flexible test data creation
|
|
291
|
+
- **Realistic Data:** Use realistic but not real user data
|
|
292
|
+
- **Data Relationships:** Handle related entity creation
|
|
293
|
+
- **Data Cleanup:** Ensure test data doesn't leak between tests
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
// Example test factory
|
|
297
|
+
export class UserFactory {
|
|
298
|
+
static build(overrides: Partial<User> = {}): User {
|
|
299
|
+
return {
|
|
300
|
+
id: faker.string.uuid(),
|
|
301
|
+
email: faker.internet.email(),
|
|
302
|
+
name: faker.person.fullName(),
|
|
303
|
+
createdAt: new Date(),
|
|
304
|
+
updatedAt: new Date(),
|
|
305
|
+
...overrides,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
static buildMany(count: number, overrides?: Partial<User>): User[] {
|
|
310
|
+
return Array.from({ length: count }, () => this.build(overrides));
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Database Seeding and Fixtures
|
|
316
|
+
|
|
317
|
+
- **Seed Scripts:** Create consistent database states
|
|
318
|
+
- **Fixture Management:** Manage test fixture lifecycle
|
|
319
|
+
- **Data Isolation:** Prevent test data interference
|
|
320
|
+
- **Cleanup Strategies:** Efficient test cleanup procedures
|
|
321
|
+
- **Snapshot Testing:** Use database snapshots for complex scenarios
|
|
322
|
+
|
|
323
|
+
## Security Testing
|
|
324
|
+
|
|
325
|
+
### Authentication Testing
|
|
326
|
+
|
|
327
|
+
- **Token Validation:** Test JWT token validation
|
|
328
|
+
- **Password Security:** Test password hashing and validation
|
|
329
|
+
- **Brute Force Protection:** Test rate limiting and account lockout
|
|
330
|
+
- **Session Security:** Test session hijacking prevention
|
|
331
|
+
- **Multi-Factor Authentication:** Test MFA implementation
|
|
332
|
+
|
|
333
|
+
### Authorization Testing
|
|
334
|
+
|
|
335
|
+
- **Role-Based Access:** Test different user roles and permissions
|
|
336
|
+
- **Resource Access:** Test access to protected resources
|
|
337
|
+
- **Privilege Escalation:** Test prevention of privilege escalation
|
|
338
|
+
- **Cross-Tenant Access:** Test multi-tenant isolation
|
|
339
|
+
- **API Security:** Test API authentication and authorization
|
|
340
|
+
|
|
341
|
+
### Vulnerability Testing
|
|
342
|
+
|
|
343
|
+
- **Input Validation:** Test for injection attacks
|
|
344
|
+
- **Cross-Site Scripting:** Test XSS prevention
|
|
345
|
+
- **Cross-Site Request Forgery:** Test CSRF protection
|
|
346
|
+
- **Dependency Scanning:** Test for vulnerable dependencies
|
|
347
|
+
- **Security Headers:** Test security header implementation
|
|
348
|
+
|
|
349
|
+
## Test Environment Management
|
|
350
|
+
|
|
351
|
+
### Environment Isolation
|
|
352
|
+
|
|
353
|
+
- **Test Containers:** Use Docker containers for isolation
|
|
354
|
+
- **Environment Variables:** Manage test-specific configuration
|
|
355
|
+
- **Service Mocking:** Mock external services appropriately
|
|
356
|
+
- **Database Isolation:** Separate test databases
|
|
357
|
+
- **Network Isolation:** Isolate test network traffic
|
|
358
|
+
|
|
359
|
+
### Continuous Integration Testing
|
|
360
|
+
|
|
361
|
+
- **Pipeline Integration:** Run tests in CI/CD pipelines
|
|
362
|
+
- **Parallel Testing:** Run tests in parallel for speed
|
|
363
|
+
- **Test Reporting:** Generate comprehensive test reports
|
|
364
|
+
- **Coverage Reporting:** Track and report test coverage
|
|
365
|
+
- **Failure Analysis:** Analyze and debug test failures
|
|
366
|
+
|
|
367
|
+
### Test Monitoring and Metrics
|
|
368
|
+
|
|
369
|
+
- **Test Performance:** Monitor test execution time
|
|
370
|
+
- **Flaky Test Detection:** Identify and fix unreliable tests
|
|
371
|
+
- **Coverage Trends:** Track test coverage over time
|
|
372
|
+
- **Test Maintenance:** Regularly review and update tests
|
|
373
|
+
- **Quality Gates:** Enforce quality standards through testing
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 'Python-specific coding standards and best practices'
|
|
3
|
+
applyTo: '**/*.py'
|
|
4
|
+
language: 'python'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Python Coding Standards and Best Practices
|
|
8
|
+
|
|
9
|
+
## Language and Framework Preferences
|
|
10
|
+
|
|
11
|
+
- **Primary Language:** Python 3.9+ for all Python projects
|
|
12
|
+
- **Code Style:** Follow PEP 8 with Black formatter for consistent formatting
|
|
13
|
+
- **Type Hints:** Use type hints for all function signatures and complex variables
|
|
14
|
+
- **Target Compatibility:** Python 3.9+ (use modern Python features appropriately)
|
|
15
|
+
|
|
16
|
+
## Code Quality Guidelines
|
|
17
|
+
|
|
18
|
+
- **Readability:** Follow "The Zen of Python" - explicit is better than implicit
|
|
19
|
+
- **Functions:** Keep functions focused, ideally under 30 lines for better readability
|
|
20
|
+
- **Magic Numbers:** Use named constants or configuration files instead of magic numbers
|
|
21
|
+
- **Error Handling:** Use specific exception types, avoid bare `except:` clauses
|
|
22
|
+
- **Memory Management:** Be mindful of memory usage, use generators for large datasets
|
|
23
|
+
- **Async Patterns:** Use `asyncio` for I/O-bound operations, avoid blocking operations
|
|
24
|
+
|
|
25
|
+
## Naming Conventions
|
|
26
|
+
|
|
27
|
+
- **Files:** Use snake_case for file names (e.g., `user_service.py`)
|
|
28
|
+
- **Classes:** PascalCase (e.g., `UserService`, `DatabaseConnection`)
|
|
29
|
+
- **Functions/Methods:** snake_case (e.g., `get_user_by_id`, `validate_input`)
|
|
30
|
+
- **Variables:** snake_case (e.g., `user_id`, `is_valid`)
|
|
31
|
+
- **Constants:** SCREAMING_SNAKE_CASE (e.g., `MAX_RETRY_ATTEMPTS`, `DEFAULT_TIMEOUT`)
|
|
32
|
+
- **Private Attributes:** Single underscore prefix (e.g., `_internal_method`)
|
|
33
|
+
- **Name Mangling:** Double underscore prefix only when necessary (e.g., `__private_attr`)
|
|
34
|
+
|
|
35
|
+
## Code Organization
|
|
36
|
+
|
|
37
|
+
- **Single Responsibility:** One class per file for complex classes, related utilities can be grouped
|
|
38
|
+
- **Imports:** Follow PEP 8 import order (standard library, third-party, local imports)
|
|
39
|
+
- **Module Structure:** Use `__init__.py` files for package initialization and clean imports
|
|
40
|
+
- **Entry Points:** Use `if __name__ == "__main__":` for script entry points
|
|
41
|
+
|
|
42
|
+
## Python-Specific Best Practices
|
|
43
|
+
|
|
44
|
+
### Type Hints and Documentation
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from typing import List, Dict, Optional, Union
|
|
48
|
+
from dataclasses import dataclass
|
|
49
|
+
|
|
50
|
+
def process_user_data(
|
|
51
|
+
users: List[Dict[str, Union[str, int]]],
|
|
52
|
+
active_only: bool = True
|
|
53
|
+
) -> List[str]:
|
|
54
|
+
"""Process user data and return list of usernames.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
users: List of user dictionaries containing user information
|
|
58
|
+
active_only: If True, only include active users
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
List of usernames matching the criteria
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
ValueError: If user data format is invalid
|
|
65
|
+
"""
|
|
66
|
+
pass
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Error Handling Patterns
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
# Good: Specific exception handling
|
|
73
|
+
try:
|
|
74
|
+
user = get_user_by_id(user_id)
|
|
75
|
+
except UserNotFoundError as e:
|
|
76
|
+
logger.warning(f"User {user_id} not found: {e}")
|
|
77
|
+
return None
|
|
78
|
+
except DatabaseConnectionError as e:
|
|
79
|
+
logger.error(f"Database connection failed: {e}")
|
|
80
|
+
raise
|
|
81
|
+
|
|
82
|
+
# Good: Use custom exceptions
|
|
83
|
+
class ValidationError(Exception):
|
|
84
|
+
"""Raised when data validation fails."""
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
class UserNotFoundError(Exception):
|
|
88
|
+
"""Raised when requested user cannot be found."""
|
|
89
|
+
pass
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Resource Management
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
# Good: Use context managers
|
|
96
|
+
with open('data.json', 'r') as file:
|
|
97
|
+
data = json.load(file)
|
|
98
|
+
|
|
99
|
+
# Good: Create custom context managers when needed
|
|
100
|
+
from contextlib import contextmanager
|
|
101
|
+
|
|
102
|
+
@contextmanager
|
|
103
|
+
def database_transaction():
|
|
104
|
+
conn = get_connection()
|
|
105
|
+
trans = conn.begin()
|
|
106
|
+
try:
|
|
107
|
+
yield conn
|
|
108
|
+
trans.commit()
|
|
109
|
+
except Exception:
|
|
110
|
+
trans.rollback()
|
|
111
|
+
raise
|
|
112
|
+
finally:
|
|
113
|
+
conn.close()
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Performance Considerations
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
# Good: Use generators for large datasets
|
|
120
|
+
def process_large_file(filename: str):
|
|
121
|
+
with open(filename, 'r') as file:
|
|
122
|
+
for line in file:
|
|
123
|
+
yield process_line(line)
|
|
124
|
+
|
|
125
|
+
# Good: Use list comprehensions for simple transformations
|
|
126
|
+
active_users = [user for user in users if user.is_active]
|
|
127
|
+
|
|
128
|
+
# Good: Use appropriate data structures
|
|
129
|
+
from collections import defaultdict, deque
|
|
130
|
+
user_groups = defaultdict(list)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Testing Standards
|
|
134
|
+
|
|
135
|
+
### Test Framework Preferences
|
|
136
|
+
|
|
137
|
+
- **Primary Framework:** pytest for all testing
|
|
138
|
+
- **Fixtures:** Use pytest fixtures for test data and setup
|
|
139
|
+
- **Parametrized Tests:** Use `pytest.mark.parametrize` for multiple test cases
|
|
140
|
+
- **Mocking:** Use `unittest.mock` or `pytest-mock` for mocking dependencies
|
|
141
|
+
|
|
142
|
+
### Test File Organization
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# tests/test_user_service.py
|
|
146
|
+
import pytest
|
|
147
|
+
from unittest.mock import Mock, patch
|
|
148
|
+
from src.services.user_service import UserService
|
|
149
|
+
from src.exceptions import UserNotFoundError
|
|
150
|
+
|
|
151
|
+
class TestUserService:
|
|
152
|
+
@pytest.fixture
|
|
153
|
+
def user_service(self):
|
|
154
|
+
return UserService(db_connection=Mock())
|
|
155
|
+
|
|
156
|
+
@pytest.mark.parametrize("user_id,expected", [
|
|
157
|
+
(1, True),
|
|
158
|
+
(999, False),
|
|
159
|
+
])
|
|
160
|
+
def test_user_exists(self, user_service, user_id, expected):
|
|
161
|
+
# Test implementation
|
|
162
|
+
pass
|
|
163
|
+
|
|
164
|
+
def test_get_user_not_found_raises_exception(self, user_service):
|
|
165
|
+
with pytest.raises(UserNotFoundError):
|
|
166
|
+
user_service.get_user_by_id(999)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Dependency Management
|
|
170
|
+
|
|
171
|
+
### Package Management
|
|
172
|
+
|
|
173
|
+
- **Primary Tool:** Poetry for dependency management and packaging
|
|
174
|
+
- **Requirements:** Maintain both `pyproject.toml` and `requirements.txt`
|
|
175
|
+
- **Development Dependencies:** Separate dev dependencies (testing, linting, formatting)
|
|
176
|
+
- **Version Pinning:** Pin exact versions for applications, use ranges for libraries
|
|
177
|
+
|
|
178
|
+
### Virtual Environment Management
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Create and activate virtual environment
|
|
182
|
+
python -m venv venv
|
|
183
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
184
|
+
|
|
185
|
+
# Or use Poetry
|
|
186
|
+
poetry install
|
|
187
|
+
poetry shell
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Code Quality Tools
|
|
191
|
+
|
|
192
|
+
### Linting and Formatting
|
|
193
|
+
|
|
194
|
+
- **Black:** Code formatting with line length 88
|
|
195
|
+
- **isort:** Import sorting and organization
|
|
196
|
+
- **flake8:** Linting and style checking
|
|
197
|
+
- **mypy:** Static type checking
|
|
198
|
+
- **pylint:** Additional code analysis
|
|
199
|
+
|
|
200
|
+
### Configuration Examples
|
|
201
|
+
|
|
202
|
+
```toml
|
|
203
|
+
# pyproject.toml
|
|
204
|
+
[tool.black]
|
|
205
|
+
line-length = 88
|
|
206
|
+
target-version = ['py39']
|
|
207
|
+
|
|
208
|
+
[tool.isort]
|
|
209
|
+
profile = "black"
|
|
210
|
+
multi_line_output = 3
|
|
211
|
+
|
|
212
|
+
[tool.mypy]
|
|
213
|
+
python_version = "3.9"
|
|
214
|
+
strict = true
|
|
215
|
+
ignore_missing_imports = true
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Documentation Standards
|
|
219
|
+
|
|
220
|
+
### Docstring Format
|
|
221
|
+
|
|
222
|
+
Use Google-style docstrings:
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
def calculate_user_score(
|
|
226
|
+
user_data: Dict[str, Any],
|
|
227
|
+
weights: Optional[Dict[str, float]] = None
|
|
228
|
+
) -> float:
|
|
229
|
+
"""Calculate a user's composite score based on various metrics.
|
|
230
|
+
|
|
231
|
+
This function computes a weighted score based on user activity,
|
|
232
|
+
engagement, and other factors.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
user_data: Dictionary containing user metrics and information
|
|
236
|
+
weights: Optional custom weights for score calculation.
|
|
237
|
+
Defaults to standard weights if not provided.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
Calculated score as a float between 0.0 and 100.0
|
|
241
|
+
|
|
242
|
+
Raises:
|
|
243
|
+
ValueError: If user_data is missing required fields
|
|
244
|
+
TypeError: If weights contain non-numeric values
|
|
245
|
+
|
|
246
|
+
Example:
|
|
247
|
+
>>> user = {"activity": 85, "engagement": 92}
|
|
248
|
+
>>> calculate_user_score(user)
|
|
249
|
+
88.5
|
|
250
|
+
"""
|
|
251
|
+
pass
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Security Considerations
|
|
255
|
+
|
|
256
|
+
### Input Validation
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
import re
|
|
260
|
+
from typing import Any
|
|
261
|
+
|
|
262
|
+
def validate_email(email: str) -> bool:
|
|
263
|
+
"""Validate email format using regex."""
|
|
264
|
+
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
|
265
|
+
return bool(re.match(pattern, email))
|
|
266
|
+
|
|
267
|
+
def sanitize_user_input(user_input: str) -> str:
|
|
268
|
+
"""Sanitize user input to prevent injection attacks."""
|
|
269
|
+
# Remove potentially dangerous characters
|
|
270
|
+
safe_input = re.sub(r'[<>"\';]', '', user_input)
|
|
271
|
+
return safe_input.strip()
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Environment Configuration
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
import os
|
|
278
|
+
from dataclasses import dataclass
|
|
279
|
+
|
|
280
|
+
@dataclass
|
|
281
|
+
class Config:
|
|
282
|
+
"""Application configuration from environment variables."""
|
|
283
|
+
database_url: str = os.getenv('DATABASE_URL', 'sqlite:///default.db')
|
|
284
|
+
secret_key: str = os.getenv('SECRET_KEY', 'dev-key-change-in-production')
|
|
285
|
+
debug: bool = os.getenv('DEBUG', 'False').lower() == 'true'
|
|
286
|
+
|
|
287
|
+
def __post_init__(self):
|
|
288
|
+
if self.secret_key == 'dev-key-change-in-production' and not self.debug:
|
|
289
|
+
raise ValueError("SECRET_KEY must be set in production")
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Common Anti-Patterns to Avoid
|
|
293
|
+
|
|
294
|
+
- **Mutable Default Arguments:** Use `None` and check inside function
|
|
295
|
+
- **Broad Exception Catching:** Avoid bare `except:` clauses
|
|
296
|
+
- **Global Variables:** Minimize global state, use dependency injection
|
|
297
|
+
- **String Concatenation in Loops:** Use `join()` for multiple strings
|
|
298
|
+
- **Not Using Context Managers:** Always use `with` for file operations
|
|
299
|
+
- **Ignoring PEP 8:** Follow Python style guidelines consistently
|
|
300
|
+
- **Missing Type Hints:** Add type hints for better code documentation
|
|
301
|
+
- **Circular Imports:** Structure modules to avoid circular dependencies
|
|
302
|
+
|
|
303
|
+
## Performance Optimization
|
|
304
|
+
|
|
305
|
+
### Memory Efficiency
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
# Use generators for large datasets
|
|
309
|
+
def read_large_file(filename: str):
|
|
310
|
+
with open(filename, 'r') as file:
|
|
311
|
+
for line in file:
|
|
312
|
+
yield line.strip()
|
|
313
|
+
|
|
314
|
+
# Use __slots__ for classes with many instances
|
|
315
|
+
class Point:
|
|
316
|
+
__slots__ = ['x', 'y']
|
|
317
|
+
|
|
318
|
+
def __init__(self, x: float, y: float):
|
|
319
|
+
self.x = x
|
|
320
|
+
self.y = y
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Concurrency Patterns
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
import asyncio
|
|
327
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
328
|
+
|
|
329
|
+
async def process_data_async(data_list: List[str]) -> List[str]:
|
|
330
|
+
"""Process data asynchronously for I/O bound operations."""
|
|
331
|
+
tasks = [process_item_async(item) for item in data_list]
|
|
332
|
+
return await asyncio.gather(*tasks)
|
|
333
|
+
|
|
334
|
+
def process_cpu_intensive_data(data_list: List[str]) -> List[str]:
|
|
335
|
+
"""Use thread pool for CPU-intensive operations."""
|
|
336
|
+
with ThreadPoolExecutor(max_workers=4) as executor:
|
|
337
|
+
results = list(executor.map(cpu_intensive_process, data_list))
|
|
338
|
+
return results
|
|
339
|
+
```
|