| from __future__ import annotations |
| from dataclasses import dataclass, field |
| from datetime import datetime |
| from typing import Optional |
| import uuid |
|
|
|
|
| def _uid() -> str: |
| return str(uuid.uuid4()) |
|
|
| def _now() -> datetime: |
| return datetime.utcnow() |
|
|
|
|
| @dataclass |
| class User: |
| name: str |
| email: str |
| id: str = field(default_factory=_uid) |
| role: str = "user" |
| active: bool = True |
| created_at: datetime = field(default_factory=_now) |
|
|
| def deactivate(self) -> None: |
| self.active = False |
|
|
| def promote(self, role: str = "admin") -> None: |
| self.role = role |
|
|
| def to_dict(self) -> dict: |
| return { |
| "id": self.id, "name": self.name, "email": self.email, |
| "role": self.role, "active": self.active, |
| "created_at": self.created_at.isoformat(), |
| } |
|
|
| @classmethod |
| def from_dict(cls, d: dict) -> User: |
| return cls( |
| id=d.get("id", _uid()), name=d["name"], email=d["email"], |
| role=d.get("role", "user"), active=d.get("active", True), |
| ) |
|
|
|
|
| @dataclass |
| class Record: |
| title: str |
| owner_id: str |
| id: str = field(default_factory=_uid) |
| tags: list[str] = field(default_factory=list) |
| active: bool = True |
| created_at: datetime = field(default_factory=_now) |
| updated_at: Optional[datetime] = None |
|
|
| def touch(self) -> None: |
| self.updated_at = _now() |
|
|
| def add_tag(self, tag: str) -> None: |
| if tag and tag not in self.tags: |
| self.tags.append(tag) |
|
|
| def remove_tag(self, tag: str) -> None: |
| self.tags = [t for t in self.tags if t != tag] |
|
|
| def update(self, **kw) -> None: |
| for k, v in kw.items(): |
| if hasattr(self, k): |
| setattr(self, k, v) |
| self.touch() |
|
|
| def to_dict(self) -> dict: |
| return { |
| "id": self.id, "title": self.title, "owner_id": self.owner_id, |
| "tags": self.tags, "active": self.active, |
| "created_at": self.created_at.isoformat(), |
| "updated_at": self.updated_at.isoformat() if self.updated_at else None, |
| } |
|
|