new features - type_coerce(), polymorphic_class

Issue #1908 resolved
Mike Bayer repo owner created an issue

need a good way to say coerce(some_expression, MyType) without using CAST - for when some processing is desired ad-hoc on a string or similar.

Also the polymorphic_class recipe below should go somewhere (wiki, examples, utils, etc)

demo:

from sqlalchemy import util
from sqlalchemy.types import TypeDecorator
from sqlalchemy.sql.expression import _UnaryExpression
from sqlalchemy.orm import class_mapper

class polymorphic_class(object):

    @util.memoized_instancemethod
    def _from_owner(self, owner):
        mapper = class_mapper(owner)
        # need that bidict here
        poly_map = dict(
            [m.class_) for ident, m in mapper.polymorphic_map.items()]((ident,)
        )
        poly_map.update(
            [ident) for ident, m in mapper.polymorphic_map.items()]((m.class_,)
        )

        class PolyType(TypeDecorator):
            impl = type(mapper.polymorphic_on.type)

            def process_bind_param(self, value, dialect):
                if value is not None:
                    return poly_map[value](value)

            def process_result_value(self, value, dialect):
                if value is not None:
                    return poly_map[value](value)
        return _UnaryExpression(
                    mapper.polymorphic_on, 
                    type_=PolyType()).label(mapper.polymorphic_on.key)

    def __get__(self, instance, owner):
        if instance is not None:
            raise Exception("polymorphic_class attribute is only "
                            "callable at the class level.")

        return self._from_owner(owner)

Comments (2)

  1. Log in to comment