Source code for fictive.transform.ext.sqlalchemy
"""
Integrating Transform with SQLAlchemy
"""
import argparse
from functools import cached_property
import sqlalchemy
from fictive.transform import Transform
[docs]class TransformColumnType(sqlalchemy.types.TypeDecorator):
"""
A TypeDecorator (i.e., SQLAlchemy column type) that automatically applies a transform
"""
impl = sqlalchemy.types.TypeEngine
[docs] def __init__(
self, base_type, transform, *args, pass_null=True, **kwargs):
if not isinstance(transform, Transform):
raise TypeError('`transform` must be a `Transform` object')
self.__base_type = base_type
self.__base_type_args = argparse.Namespace(args=args, kwargs=kwargs)
self.__transform = transform
self.__pass_null = pass_null
super().__init__(*args, **kwargs)
@cached_property
def __impl(self):
if isinstance(self.__base_type, type):
return self.__base_type(
*self.__base_type_args.args, **self.__base_type_args.kwargs)
return self.__base_type
@property
def python_type(self): # pragma: no cover
raise NotImplementedError()
[docs] def process_bind_param(self, value, dialect):
"""
reverse transform of external value to database value
"""
if value is None and self.__pass_null:
return None
return self.__transform.inverse_operation(value)
[docs] def process_result_value(self, value, dialect):
"""
transform database value to external value
"""
if value is None and self.__pass_null:
return None
return self.__transform(value)
[docs] def process_literal_param(self, value, dialect): # pragma: no cover
return self.process_bind_param(value, dialect)