Add data persistence models
This commit is contained in:
14
src/py_dvt_ate/data/__init__.py
Normal file
14
src/py_dvt_ate/data/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
"""Data persistence layer.
|
||||||
|
|
||||||
|
Provides storage for test runs, results, and measurements using
|
||||||
|
SQLite for metadata and Parquet for time-series data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from py_dvt_ate.data.models import Measurement, TestResult, TestRun, TestStatus
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Measurement",
|
||||||
|
"TestResult",
|
||||||
|
"TestRun",
|
||||||
|
"TestStatus",
|
||||||
|
]
|
||||||
83
src/py_dvt_ate/data/models.py
Normal file
83
src/py_dvt_ate/data/models.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
"""Data models for test persistence.
|
||||||
|
|
||||||
|
This module defines dataclasses representing test runs, results, and measurements.
|
||||||
|
These models map to SQLite tables (for metadata) and Parquet files (for time-series).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class TestStatus(Enum):
|
||||||
|
"""Test run status."""
|
||||||
|
|
||||||
|
PENDING = "pending"
|
||||||
|
RUNNING = "running"
|
||||||
|
PASSED = "passed"
|
||||||
|
FAILED = "failed"
|
||||||
|
ERROR = "error"
|
||||||
|
SKIPPED = "skipped"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TestRun:
|
||||||
|
"""Test run metadata.
|
||||||
|
|
||||||
|
Maps to the test_runs SQLite table.
|
||||||
|
"""
|
||||||
|
|
||||||
|
id: str # UUID
|
||||||
|
test_name: str
|
||||||
|
started_at: datetime
|
||||||
|
status: TestStatus
|
||||||
|
config_json: str # JSON string of test configuration
|
||||||
|
description: str | None = None
|
||||||
|
completed_at: datetime | None = None
|
||||||
|
operator: str | None = None
|
||||||
|
notes: str | None = None
|
||||||
|
created_at: datetime = field(default_factory=datetime.now)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class TestResult:
|
||||||
|
"""Immutable test result with limits.
|
||||||
|
|
||||||
|
Maps to the test_results SQLite table.
|
||||||
|
Represents a single scalar measurement with pass/fail limits.
|
||||||
|
"""
|
||||||
|
|
||||||
|
id: str # UUID
|
||||||
|
test_run_id: str # Foreign key to test_runs.id
|
||||||
|
parameter: str
|
||||||
|
value: float
|
||||||
|
unit: str
|
||||||
|
measured_at: datetime
|
||||||
|
lower_limit: float | None = None
|
||||||
|
upper_limit: float | None = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def passed(self) -> bool | None:
|
||||||
|
"""Evaluate pass/fail. None if no limits defined."""
|
||||||
|
if self.lower_limit is None and self.upper_limit is None:
|
||||||
|
return None
|
||||||
|
lower_ok = self.lower_limit is None or self.value >= self.lower_limit
|
||||||
|
upper_ok = self.upper_limit is None or self.value <= self.upper_limit
|
||||||
|
return lower_ok and upper_ok
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Measurement:
|
||||||
|
"""Immutable measurement record for time-series data.
|
||||||
|
|
||||||
|
Maps to Parquet files for efficient storage and analysis.
|
||||||
|
Includes measurement conditions (temperature, voltage, current) at time of measurement.
|
||||||
|
"""
|
||||||
|
|
||||||
|
timestamp: float # Seconds since epoch (high precision)
|
||||||
|
parameter: str
|
||||||
|
value: float
|
||||||
|
unit: str
|
||||||
|
temperature: float = 0.0 # Chamber temperature at measurement
|
||||||
|
input_voltage: float = 0.0 # DUT input voltage at measurement
|
||||||
|
load_current: float = 0.0 # DUT load current at measurement
|
||||||
Reference in New Issue
Block a user