Files
tracker-cli/tracker/services/session_service.py
Daniel Arroyo 4547c492da Implement storage layer for MVP-1 Personal Tracker CLI
Add storage layer with FileStorage, MarkdownReader, and MarkdownWriter classes.
Add data models (Project, Session, Note, Change).
2026-03-23 08:54:00 -03:00

68 lines
2.0 KiB
Python

"""Session service for active session management."""
import json
from datetime import datetime
from pathlib import Path
from typing import Optional
from ..models import Session
_ACTIVE_SESSION_FILE = ".active_session.json"
def get_active_session_path() -> Path:
"""Return the path to the active session file in projects/ directory."""
return Path("projects") / _ACTIVE_SESSION_FILE
def get_active_session() -> Optional[Session]:
"""Load and return the currently active session, or None if none exists."""
path = get_active_session_path()
if not path.exists():
return None
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
# Convert started_at string back to datetime
data["started_at"] = datetime.fromisoformat(data["started_at"])
if data.get("ended_at"):
data["ended_at"] = datetime.fromisoformat(data["ended_at"])
return Session(**data)
def set_active_session(session: Session) -> None:
"""Save the given session as the active session."""
path = get_active_session_path()
path.parent.mkdir(parents=True, exist_ok=True)
data = session.model_dump(mode="json")
# Serialize datetime objects to ISO format
data["started_at"] = session.started_at.isoformat()
if session.ended_at:
data["ended_at"] = session.ended_at.isoformat()
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
def clear_active_session() -> None:
"""Remove the active session file."""
path = get_active_session_path()
if path.exists():
path.unlink()
def validate_no_other_active_session(project_slug: str) -> bool:
"""
Check if there is an active session for a different project.
Returns True if no conflict exists (i.e., either no active session
or the active session belongs to the same project).
"""
active = get_active_session()
if active is None:
return True
return active.project_slug == project_slug