Source code for simdb.database.models.types
import enum
import uuid
from enum import Enum
from typing import Optional, Dict
from sqlalchemy import types as sql_types
from ... import uri as urilib
[docs]
class UUID(sql_types.TypeDecorator):
"""
Platform-independent GUID type.
Uses PostgreSQL's UUID type, otherwise uses CHAR(32), storing as stringified hex values.
"""
impl = sql_types.CHAR
cache_ok = True
@property
def python_type(self):
return uuid.UUID
[docs]
def load_dialect_impl(self, dialect):
from sqlalchemy.dialects import postgresql
if dialect.name == "postgresql":
return dialect.type_descriptor(postgresql.UUID())
else:
return dialect.type_descriptor(sql_types.CHAR(32))
[docs]
def process_bind_param(self, value, dialect):
if value is None:
return value
elif dialect.name == "postgresql":
return str(value)
else:
if not isinstance(value, uuid.UUID):
try:
return uuid.UUID(value).hex
except ValueError:
return value
else:
return value.hex
[docs]
def process_result_value(self, value, dialect):
if value is None:
return value
else:
if not isinstance(value, uuid.UUID):
value = uuid.UUID(value)
return value
[docs]
def process_literal_param(self, value, dialect):
return self.process_result_value(value, dialect)
[docs]
class URI(sql_types.TypeDecorator):
"""
UUID type for reading/writing to the ORM.
"""
impl = sql_types.VARCHAR
@property
def python_type(self):
return urilib.URI
[docs]
def process_bind_param(self, value: Optional[urilib.URI], dialect) -> Optional[str]:
if value is None:
return value
return str(value)
[docs]
def process_result_value(
self, value: Optional[str], dialect
) -> Optional[urilib.URI]:
if value is None:
return value
return urilib.URI(value)
[docs]
def process_literal_param(self, value, dialect) -> Optional[urilib.URI]:
return self.process_result_value(value, dialect)
[docs]
class ChoiceType(sql_types.TypeDecorator):
impl = sql_types.CHAR
@property
def python_type(self):
return str
def __init__(self, choices: Dict[Enum, str], enum_type: type, **kw):
if type(enum_type) is not enum.EnumMeta:
raise ValueError("enum_type must be a class inheriting from enum.Enum.")
self._enum_type = enum_type
self._choices_inverse = dict(choices)
self._choices = {v: k for k, v in self._choices_inverse.items()}
if len(self._choices) != len(self._choices_inverse):
raise TypeError("Values in choices dict must be unique")
super().__init__(**kw)
[docs]
def process_bind_param(self, value: str, dialect):
return self._choices_inverse[self._enum_type(value)]
[docs]
def process_result_value(self, value: str, dialect):
return self._choices[value]
[docs]
def process_literal_param(self, value, dialect):
return self.process_result_value(value, dialect)