Coverage for src/paperap/models/abstract/meta.py: 100%
31 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-11 21:37 -0400
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-11 21:37 -0400
1"""
2----------------------------------------------------------------------------
4 METADATA:
6 File: meta.py
7 Project: paperap
8 Created: 2025-03-07
9 Version: 0.0.5
10 Author: Jess Mann
11 Email: jess@jmann.me
12 Copyright (c) 2025 Jess Mann
14----------------------------------------------------------------------------
16 LAST MODIFIED:
18 2025-03-07 By Jess Mann
20"""
22from __future__ import annotations
24from typing import TYPE_CHECKING, Any, Iterable, Literal
26from paperap.const import ModelStatus
28if TYPE_CHECKING:
29 from paperap.models.abstract import BaseModel
32class StatusContext:
33 """
34 Context manager for safely updating model status.
36 Attributes:
37 model (SomeModel): The model whose status is being updated.
38 new_status (ModelStatus): The status to set within the context.
39 previous_status (ModelStatus): The status before entering the context.
41 Examples:
42 >>> class SomeModel(BaseModel):
43 ... def perform_update(self):
44 ... with StatusContext(self, ModelStatus.UPDATING):
45 ... # Perform an update
47 """
49 _model: "BaseModel"
50 _new_status: ModelStatus
51 _previous_status: ModelStatus | None
53 @property
54 def model(self) -> "BaseModel":
55 """Read-only access to the model."""
56 return self._model
58 @property
59 def _meta(self) -> "BaseModel.Meta":
60 """Read-only access to the model's meta."""
61 return self.model._meta # pyright: ignore[reportPrivateUsage] # pylint: disable=protected-access
63 @property
64 def new_status(self) -> ModelStatus:
65 """Read-only access to the new status."""
66 return self._new_status
68 @property
69 def previous_status(self) -> ModelStatus | None:
70 """Read-only access to the previous status."""
71 return self._previous_status
73 def __init__(self, model: "BaseModel", new_status: ModelStatus) -> None:
74 self._model = model
75 self._new_status = new_status
76 self._previous_status = None
77 super().__init__()
79 def __enter__(self) -> None:
80 self._previous_status = self._meta.status
81 self._meta.status = self.new_status
82 # Do NOT return context manager, because we want to guarantee that the status is reverted
83 # so we do not want to allow access to the context manager object
85 def __exit__(
86 self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: Iterable[Any]
87 ) -> None:
88 if self.previous_status is not None:
89 self._meta.status = self.previous_status
90 else:
91 self._meta.status = ModelStatus.ERROR