feat: use custom type to handle existing naive datetimes
This commit is contained in:
parent
e22abb383c
commit
39bdac1ecf
45 changed files with 210 additions and 84 deletions
|
@ -7,6 +7,7 @@ from sqlalchemy.orm import Mapped, mapped_column
|
|||
|
||||
from app.brm.brn import BRN
|
||||
from app.extensions import db
|
||||
from app.models.types import AwareDateTime
|
||||
|
||||
|
||||
class AbstractConfiguration(db.Model): # type: ignore
|
||||
|
@ -14,9 +15,9 @@ class AbstractConfiguration(db.Model): # type: ignore
|
|||
|
||||
id: Mapped[int] = mapped_column(db.Integer, primary_key=True)
|
||||
description: Mapped[str]
|
||||
added: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
updated: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
destroyed: Mapped[Optional[datetime]] = mapped_column(db.DateTime(timezone=True), nullable=True)
|
||||
added: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
updated: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
destroyed: Mapped[Optional[datetime]] = mapped_column(AwareDateTime(), nullable=True)
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
|
@ -43,7 +44,7 @@ class Deprecation(db.Model): # type: ignore[name-defined,misc]
|
|||
id: Mapped[int] = mapped_column(db.Integer, primary_key=True)
|
||||
resource_type: Mapped[str]
|
||||
resource_id: Mapped[int]
|
||||
deprecated_at: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
deprecated_at: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
meta: Mapped[Optional[Dict[str, Any]]] = mapped_column(db.JSON())
|
||||
reason: Mapped[str]
|
||||
|
||||
|
@ -58,11 +59,11 @@ class AbstractResource(db.Model): # type: ignore
|
|||
__abstract__ = True
|
||||
|
||||
id: Mapped[int] = mapped_column(db.Integer, primary_key=True)
|
||||
added: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
updated: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
deprecated: Mapped[Optional[datetime]] = mapped_column(db.DateTime(timezone=True), nullable=True)
|
||||
added: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
updated: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
deprecated: Mapped[Optional[datetime]] = mapped_column(AwareDateTime(), nullable=True)
|
||||
deprecation_reason: Mapped[Optional[str]]
|
||||
destroyed: Mapped[Optional[datetime]] = mapped_column(db.DateTime(timezone=True), nullable=True)
|
||||
destroyed: Mapped[Optional[datetime]] = mapped_column(AwareDateTime(), nullable=True)
|
||||
|
||||
def __init__(self, *,
|
||||
id: Optional[int] = None,
|
||||
|
|
|
@ -7,6 +7,7 @@ from sqlalchemy.orm import Mapped, mapped_column
|
|||
from app.brm.brn import BRN
|
||||
from app.extensions import db
|
||||
from app.models import AbstractConfiguration
|
||||
from app.models.types import AwareDateTime
|
||||
|
||||
|
||||
class Activity(db.Model): # type: ignore
|
||||
|
@ -14,7 +15,7 @@ class Activity(db.Model): # type: ignore
|
|||
group_id: Mapped[Optional[int]]
|
||||
activity_type: Mapped[str]
|
||||
text: Mapped[str]
|
||||
added: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
added: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
|
||||
def __init__(self, *,
|
||||
id: Optional[int] = None,
|
||||
|
|
|
@ -6,6 +6,7 @@ from sqlalchemy.orm import Mapped, mapped_column
|
|||
|
||||
from app.extensions import db
|
||||
from app.models.activity import Activity
|
||||
from app.models.types import AwareDateTime
|
||||
|
||||
|
||||
class AlarmState(enum.Enum):
|
||||
|
@ -30,8 +31,8 @@ class Alarm(db.Model): # type: ignore
|
|||
target: Mapped[str]
|
||||
aspect: Mapped[str]
|
||||
alarm_state: Mapped[AlarmState] = mapped_column(default=AlarmState.UNKNOWN)
|
||||
state_changed: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
last_updated: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
state_changed: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
last_updated: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
text: Mapped[str]
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -7,6 +7,7 @@ from sqlalchemy.orm import Mapped, mapped_column
|
|||
from app.brm.brn import BRN
|
||||
from app.extensions import db
|
||||
from app.models import AbstractConfiguration, AbstractResource
|
||||
from app.models.types import AwareDateTime
|
||||
|
||||
|
||||
class AutomationState(enum.Enum):
|
||||
|
@ -19,8 +20,8 @@ class Automation(AbstractConfiguration):
|
|||
short_name: Mapped[str]
|
||||
state: Mapped[AutomationState] = mapped_column(default=AutomationState.IDLE)
|
||||
enabled: Mapped[bool]
|
||||
last_run: Mapped[Optional[datetime]] = mapped_column(db.DateTime(timezone=True))
|
||||
next_run: Mapped[Optional[datetime]] = mapped_column(db.DateTime(timezone=True))
|
||||
last_run: Mapped[Optional[datetime]] = mapped_column(AwareDateTime())
|
||||
next_run: Mapped[Optional[datetime]] = mapped_column(AwareDateTime())
|
||||
next_is_full: Mapped[bool]
|
||||
|
||||
logs = db.relationship("AutomationLogs", back_populates="automation")
|
||||
|
|
|
@ -8,6 +8,7 @@ from app.brm.brn import BRN
|
|||
from app.extensions import db
|
||||
from app.models import AbstractConfiguration, AbstractResource
|
||||
from app.models.base import Pool
|
||||
from app.models.types import AwareDateTime
|
||||
|
||||
|
||||
class ProviderAllocation(enum.Enum):
|
||||
|
@ -54,7 +55,7 @@ class BridgeConf(AbstractConfiguration):
|
|||
class Bridge(AbstractResource):
|
||||
conf_id: Mapped[int] = mapped_column(db.ForeignKey("bridge_conf.id"))
|
||||
cloud_account_id: Mapped[int] = mapped_column(db.ForeignKey("cloud_account.id"))
|
||||
terraform_updated: Mapped[Optional[datetime]] = mapped_column(db.DateTime(timezone=True), nullable=True)
|
||||
terraform_updated: Mapped[Optional[datetime]] = mapped_column(AwareDateTime(), nullable=True)
|
||||
nickname: Mapped[Optional[str]]
|
||||
fingerprint: Mapped[Optional[str]]
|
||||
hashed_fingerprint: Mapped[Optional[str]]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import enum
|
||||
from typing import Any, Dict, List, TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Any, Dict, List
|
||||
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
|
@ -8,7 +8,6 @@ from app.extensions import db
|
|||
from app.models import AbstractConfiguration
|
||||
from app.models.mirrors import StaticOrigin
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.models.bridges import Bridge
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ from app.extensions import db
|
|||
from app.models import AbstractConfiguration, AbstractResource, Deprecation
|
||||
from app.models.base import Group, Pool
|
||||
from app.models.onions import Onion
|
||||
from app.models.types import AwareDateTime
|
||||
|
||||
country_origin = db.Table(
|
||||
'country_origin',
|
||||
|
@ -275,7 +276,7 @@ class Proxy(AbstractResource):
|
|||
provider: Mapped[str] = mapped_column(db.String(20), nullable=False)
|
||||
psg: Mapped[Optional[int]] = mapped_column(db.Integer, nullable=True)
|
||||
slug: Mapped[Optional[str]] = mapped_column(db.String(20), nullable=True)
|
||||
terraform_updated: Mapped[Optional[datetime]] = mapped_column(db.DateTime(timezone=True), nullable=True)
|
||||
terraform_updated: Mapped[Optional[datetime]] = mapped_column(AwareDateTime(), nullable=True)
|
||||
url: Mapped[Optional[str]] = mapped_column(db.String(255), nullable=True)
|
||||
|
||||
origin: Mapped[Origin] = relationship("Origin", back_populates="proxies")
|
||||
|
|
|
@ -7,6 +7,7 @@ from app.brm.brn import BRN
|
|||
from app.extensions import db
|
||||
from app.models import AbstractConfiguration, AbstractResource
|
||||
from app.models.base import Group
|
||||
from app.models.types import AwareDateTime
|
||||
from app.util.onion import onion_hostname
|
||||
|
||||
|
||||
|
@ -36,7 +37,7 @@ class Onion(AbstractConfiguration):
|
|||
|
||||
group_id: Mapped[int] = mapped_column(db.ForeignKey("group.id"))
|
||||
domain_name: Mapped[str]
|
||||
cert_expiry: Mapped[datetime] = mapped_column(db.DateTime(timezone=True))
|
||||
cert_expiry: Mapped[datetime] = mapped_column(AwareDateTime())
|
||||
cert_sans: Mapped[str]
|
||||
onion_public_key: Mapped[bytes]
|
||||
onion_private_key: Mapped[bytes]
|
||||
|
|
21
app/models/types.py
Normal file
21
app/models/types.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from datetime import timezone
|
||||
|
||||
from sqlalchemy import DateTime, TypeDecorator
|
||||
|
||||
|
||||
class AwareDateTime(TypeDecorator):
|
||||
impl = DateTime(timezone=True)
|
||||
|
||||
cache_ok = True
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
# Ensure the value is aware. If it's naive, assume UTC.
|
||||
if value is not None and value.tzinfo is None:
|
||||
value = value.replace(tzinfo=timezone.utc)
|
||||
return value
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
# Ensure the value is aware. If it's naive, assume UTC.
|
||||
if value is not None and value.tzinfo is None:
|
||||
value = value.replace(tzinfo=timezone.utc)
|
||||
return value
|
Loading…
Add table
Add a link
Reference in a new issue