Skip to content

Commit 2950d74

Browse files
authored
Merge pull request #17 from blopit/fix-example
Fix example
2 parents 85ce046 + 38a8736 commit 2950d74

1,867 files changed

Lines changed: 5522 additions & 281716 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
---
2+
description: Rules and best practices for Python development in the project
3+
globs: "**/*.py"
4+
---
5+
6+
# Python Development Rules
7+
8+
## Purpose
9+
This file defines rules and best practices for Python development in the project. It ensures consistent code style, proper documentation, and adherence to Python best practices across all Python files.
10+
11+
## Glob Patterns
12+
- `**/*.py`
13+
- `src/**/*.py`
14+
- `tests/**/*.py`
15+
- `scripts/**/*.py`
16+
17+
## Rules
18+
19+
### Code Style
20+
- Follow PEP 8 style guide for all Python code
21+
- Maximum line length of 88 characters (Black formatter default)
22+
- Use 4 spaces for indentation, not tabs
23+
- Use snake_case for variables, functions, and modules
24+
- Use PascalCase for classes
25+
- Use UPPER_CASE for constants
26+
- Add a blank line at the end of each file
27+
28+
### Documentation
29+
- Include docstrings for all modules, classes, and functions
30+
- Use Google-style docstrings format
31+
- Document parameters, return values, and exceptions
32+
- Include type hints for function parameters and return values
33+
- Add comments for complex or non-obvious code sections
34+
35+
### Imports
36+
- Group imports in the following order:
37+
1. Standard library imports
38+
2. Third-party library imports
39+
3. Local application imports
40+
- Sort imports alphabetically within each group
41+
- Use absolute imports rather than relative imports when possible
42+
- Avoid wildcard imports (`from module import *`)
43+
44+
### Error Handling
45+
- Use specific exception types rather than catching all exceptions
46+
- Include meaningful error messages
47+
- Log exceptions with appropriate context
48+
- Clean up resources in finally blocks or use context managers
49+
50+
### Testing
51+
- Write unit tests for all functions and classes
52+
- Use pytest for testing
53+
- Name test files with `test_` prefix
54+
- Name test functions with `test_` prefix
55+
- Use fixtures for common setup and teardown
56+
- Aim for high test coverage (>80%)
57+
58+
## Examples
59+
60+
### Good Code Style
61+
62+
```python
63+
"""
64+
User management module.
65+
66+
This module provides functionality for managing users in the system.
67+
"""
68+
69+
import logging
70+
import os
71+
from typing import Dict, List, Optional
72+
73+
import requests
74+
from pydantic import BaseModel
75+
76+
from myapp.database import db_session
77+
from myapp.utils import format_username
78+
79+
80+
class User:
81+
"""
82+
User class representing a system user.
83+
84+
Attributes:
85+
username (str): The user's username
86+
email (str): The user's email address
87+
is_active (bool): Whether the user is active
88+
"""
89+
90+
def __init__(self, username: str, email: str, is_active: bool = True):
91+
"""
92+
Initialize a new User.
93+
94+
Args:
95+
username (str): The user's username
96+
email (str): The user's email address
97+
is_active (bool, optional): Whether the user is active. Defaults to True.
98+
"""
99+
self.username = username
100+
self.email = email
101+
self.is_active = is_active
102+
103+
def get_display_name(self) -> str:
104+
"""
105+
Get the user's display name.
106+
107+
Returns:
108+
str: The formatted display name
109+
"""
110+
return format_username(self.username)
111+
112+
113+
def get_user_by_id(user_id: int) -> Optional[User]:
114+
"""
115+
Get a user by their ID.
116+
117+
Args:
118+
user_id (int): The user's ID
119+
120+
Returns:
121+
Optional[User]: The user if found, None otherwise
122+
123+
Raises:
124+
ValueError: If user_id is negative
125+
"""
126+
if user_id < 0:
127+
raise ValueError("User ID cannot be negative")
128+
129+
try:
130+
# Query the database for the user
131+
user_data = db_session.query(f"SELECT * FROM users WHERE id = {user_id}")
132+
if not user_data:
133+
return None
134+
135+
return User(
136+
username=user_data["username"],
137+
email=user_data["email"],
138+
is_active=user_data["is_active"]
139+
)
140+
except Exception as e:
141+
logging.error(f"Error retrieving user {user_id}: {str(e)}")
142+
return None
143+
```
144+
145+
### Good Test Example
146+
147+
```python
148+
"""
149+
Tests for the user management module.
150+
"""
151+
152+
import pytest
153+
154+
from myapp.users import User, get_user_by_id
155+
156+
157+
@pytest.fixture
158+
def mock_db_session(monkeypatch):
159+
"""Fixture to mock the database session."""
160+
class MockDBSession:
161+
def query(self, query_string):
162+
if "WHERE id = 1" in query_string:
163+
return {"username": "testuser", "email": "test@example.com", "is_active": True}
164+
return None
165+
166+
monkeypatch.setattr("myapp.database.db_session", MockDBSession())
167+
168+
169+
def test_user_initialization():
170+
"""Test User class initialization."""
171+
user = User(username="testuser", email="test@example.com")
172+
173+
assert user.username == "testuser"
174+
assert user.email == "test@example.com"
175+
assert user.is_active is True
176+
177+
178+
def test_get_user_by_id_success(mock_db_session):
179+
"""Test successful user retrieval."""
180+
user = get_user_by_id(1)
181+
182+
assert user is not None
183+
assert user.username == "testuser"
184+
assert user.email == "test@example.com"
185+
186+
187+
def test_get_user_by_id_not_found(mock_db_session):
188+
"""Test user not found case."""
189+
user = get_user_by_id(999)
190+
191+
assert user is None
192+
193+
194+
def test_get_user_by_id_negative_id():
195+
"""Test error handling for negative ID."""
196+
with pytest.raises(ValueError) as excinfo:
197+
get_user_by_id(-1)
198+
199+
assert "User ID cannot be negative" in str(excinfo.value)
200+
```
201+
202+
## Related MDC Files
203+
- [pytest-glob.mdc](mdc:../testing/pytest-glob.mdc)
204+
- [pydantic-glob.mdc](mdc:../validation/pydantic-glob.mdc)
205+
- [logging-glob.mdc](mdc:../utilities/logging-glob.mdc)
206+
207+
## Exceptions
208+
- Generated Python files (marked with a `# GENERATED FILE` comment) are exempt from style requirements
209+
- Migration scripts may follow different import ordering due to their specific requirements
210+
- Test files may exceed the line length limit for test data and assertions
211+
212+
## Enforcement
213+
- Black formatter is used to enforce code style
214+
- Flake8 is used to check for PEP 8 compliance
215+
- Mypy is used to check type hints
216+
- Pylint is used for additional code quality checks
217+
- Pre-commit hooks enforce these checks before commits
218+
- CI/CD pipeline includes these checks for all pull requests
219+
220+
## Version History
221+
- 2023-10-01: Initial version
222+
- 2023-11-15: Added rules for error handling
223+
- 2024-01-20: Updated docstring format to Google style
224+
- 2024-03-05: Added type hint requirements

0 commit comments

Comments
 (0)