|
| 1 | +src/repository.py: | |
| 2 | + from typing import List, Optional |
| 3 | +
|
| 4 | + class UserRepository: |
| 5 | + def __init__(self, db_connection): |
| 6 | + self.db = db_connection |
| 7 | +
|
| 8 | + def find_by_id(self, user_id: int) -> Optional[dict]: |
| 9 | + return self.db.query("SELECT * FROM users WHERE id = %s", user_id) |
| 10 | +
|
| 11 | + def find_all(self) -> List[dict]: |
| 12 | + return self.db.query("SELECT * FROM users") |
| 13 | +
|
| 14 | + def create(self, user_data: dict) -> int: |
| 15 | + return self.db.insert("users", user_data) |
| 16 | +
|
| 17 | + def update(self, user_id: int, user_data: dict) -> bool: |
| 18 | + return self.db.update("users", user_id, user_data) |
| 19 | +
|
| 20 | + def delete(self, user_id: int) -> bool: |
| 21 | + return self.db.delete("users", user_id) |
| 22 | +
|
| 23 | +src/models.py: | |
| 24 | + from dataclasses import dataclass |
| 25 | + from typing import Optional |
| 26 | + from datetime import datetime |
| 27 | +
|
| 28 | + @dataclass |
| 29 | + class User: |
| 30 | + id: int |
| 31 | + name: str |
| 32 | + email: str |
| 33 | + created_at: datetime |
| 34 | + updated_at: Optional[datetime] = None |
| 35 | +
|
| 36 | + @dataclass |
| 37 | + class UserProfile: |
| 38 | + user_id: int |
| 39 | + bio: Optional[str] = None |
| 40 | + avatar_url: Optional[str] = None |
| 41 | +
|
| 42 | +src/validators.py: | |
| 43 | + import re |
| 44 | + from typing import List |
| 45 | +
|
| 46 | + def validate_email(email: str) -> bool: |
| 47 | + pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' |
| 48 | + return bool(re.match(pattern, email)) |
| 49 | +
|
| 50 | + def validate_username(name: str) -> bool: |
| 51 | + return len(name) >= 3 and len(name) <= 50 |
| 52 | +
|
| 53 | + def validate_password(password: str) -> List[str]: |
| 54 | + errors = [] |
| 55 | + if len(password) < 8: |
| 56 | + errors.append("Password must be at least 8 characters") |
| 57 | + if not any(c.isupper() for c in password): |
| 58 | + errors.append("Password must contain uppercase letter") |
| 59 | + return errors |
| 60 | +
|
| 61 | +src/user_service.py: | |
| 62 | + from typing import List, Optional |
| 63 | + from src.repository import UserRepository |
| 64 | + from src.models import User, UserProfile |
| 65 | + from src.validators import validate_email, validate_username, validate_password |
| 66 | +
|
| 67 | + class UserService: |
| 68 | + def __init__(self, repository: UserRepository): |
| 69 | + self.repository = repository |
| 70 | +
|
| 71 | + def register_user(self, name: str, email: str, password: str) -> User: |
| 72 | + if not validate_email(email): |
| 73 | + raise ValueError("Invalid email address") |
| 74 | + if not validate_username(name): |
| 75 | + raise ValueError("Invalid username") |
| 76 | + password_errors = validate_password(password) |
| 77 | + if password_errors: |
| 78 | + raise ValueError(", ".join(password_errors)) |
| 79 | + user_data = {"name": name, "email": email, "password": password} |
| 80 | + user_id = self.repository.create(user_data) |
| 81 | + return User(id=user_id, name=name, email=email, created_at=None) |
| 82 | +
|
| 83 | + def get_user(self, user_id: int) -> Optional[User]: |
| 84 | + data = self.repository.find_by_id(user_id) |
| 85 | + if data is None: |
| 86 | + return None |
| 87 | + return User(**data) |
| 88 | +
|
| 89 | + def list_users(self) -> List[User]: |
| 90 | + rows = self.repository.find_all() |
| 91 | + return [User(**row) for row in rows] |
| 92 | +
|
| 93 | + def update_user(self, user_id: int, name: str, email: str) -> bool: |
| 94 | + if not validate_email(email): |
| 95 | + raise ValueError("Invalid email address") |
| 96 | + if not validate_username(name): |
| 97 | + raise ValueError("Invalid username") |
| 98 | + return self.repository.update(user_id, {"name": name, "email": email}) |
| 99 | +
|
| 100 | + def delete_user(self, user_id: int) -> bool: |
| 101 | + return self.repository.delete(user_id) |
| 102 | +
|
| 103 | + def get_user_profile(self, user_id: int) -> Optional[UserProfile]: |
| 104 | + data = self.repository.find_by_id(user_id) |
| 105 | + if data is None: |
| 106 | + return None |
| 107 | + return UserProfile(user_id=user_id, bio=data.get("bio"), avatar_url=data.get("avatar_url")) |
| 108 | +
|
| 109 | +scripts/GARBAGE_REG014_seed_data.py: | |
| 110 | + GARBAGE_REG014_SEED_MARKER = "seed_data_garbage" |
| 111 | + def GARBAGE_REG014_populate_database(): |
| 112 | + return "GARBAGE_REG014_POPULATE_RESULT" |
| 113 | +
|
| 114 | +scripts/GARBAGE_REG014_migrate.py: | |
| 115 | + GARBAGE_REG014_MIGRATE_MARKER = "migrate_garbage" |
| 116 | + def GARBAGE_REG014_run_migrations(): |
| 117 | + return "GARBAGE_REG014_MIGRATION_RESULT" |
| 118 | +
|
| 119 | +utils/GARBAGE_REG014_helpers.py: | |
| 120 | + GARBAGE_REG014_HELPER_MARKER = "helper_garbage" |
| 121 | + def GARBAGE_REG014_format_output(): |
| 122 | + return "GARBAGE_REG014_FORMAT_RESULT" |
0 commit comments