# Buggy code
def compiles(class_, *specs):
    """Register a function as a compiler for a
    given :class:`_expression.ClauseElement` type."""

    def decorate(fn):
        # get an existing @compiles handler
        existing = class_.__dict__.get("_compiler_dispatcher", None)

        # get the original handler.  All ClauseElement classes have one
        # of these, but some TypeEngine classes will not.
        existing_dispatch = getattr(class_, "_compiler_dispatch", None)

        if not existing:
            existing = _dispatcher()

            if existing_dispatch:

                def _wrap_existing_dispatch(element, compiler, **kw):
                    try:
                        return existing_dispatch(element, compiler, **kw)
                    except exc.UnsupportedCompilationError as uce:
                        util.raise_(
                            exc.CompileError(
                                "%s construct has no default "
                                "compilation handler." % type(element)
                            ),
                            from_=uce,
                        )

                existing.specs["default"] = _wrap_existing_dispatch

            # TODO: why is the lambda needed ?
            setattr(
                class_,
                "_compiler_dispatch",
                lambda *arg, **kw: existing(*arg, **kw),
            )
            setattr(class_, "_compiler_dispatcher", existing)

        if specs:
            for s in specs:
                existing.specs[s] = fn

        else:
            existing.specs["default"] = fn
        return fn

    return decorate


# Traceback (AttributeError)
Traceback (most recent call last):
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 89, in _compiler_dispatch
meth = getter(visitor)
AttributeError: 'StrSQLCompiler' object has no attribute 'visit_column_element'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/ext/compiler.py", line 425, in _wrap_existing_dispatch
return existing_dispatch(element, compiler, **kw)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 93, in _compiler_dispatch
replace_context=err,
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 182, in raise_
raise exception
sqlalchemy.exc.UnsupportedCompilationError: Compiler <sqlalchemy.sql.compiler.StrSQLCompiler object at 0x7f01d84cf8d0> can't render element of type <class 'sqlalchemy.sql.elements.ColumnElement'> (Background on this error at: http://sqlalche.me/e/13/l7de)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "repro.py", line 89, in <module>
main()
File "repro.py", line 85, in main
print(result)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3538, in __str__
context = self._compile_context()
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 4114, in _compile_context
context.statement = self._compound_eager_statement(context)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 4180, in _compound_eager_statement
from_clause, eager_join, eager_join.stop_on
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/util.py", line 621, in splice_joins
right.onclause = adapter.traverse(right.onclause)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 240, in traverse
return replacement_traverse(obj, self.__traverse_options__, replace)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 484, in replacement_traverse
obj = clone(obj, **opts)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 473, in clone
newelem = replace(elem)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/visitors.py", line 236, in replace
e = v.replace(elem)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/util.py", line 848, in replace
return self._corresponding_column(col, True)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/util.py", line 821, in _corresponding_column
col, require_embedded=require_embedded
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/selectable.py", line 560, in corresponding_column
if self.c.contains_column(column):
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 893, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/selectable.py", line 647, in columns
self._populate_column_collection()
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/selectable.py", line 1392, in _populate_column_collection
for col in self.element.columns._all_columns:
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 893, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/selectable.py", line 647, in columns
self._populate_column_collection()
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/selectable.py", line 3903, in _populate_column_collection
c._make_proxy(self, key=key, name=name, name_is_truncatable=True)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 844, in _make_proxy
key = str(self)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 491, in __str__
return str(self.compile())
File "<string>", line 1, in <lambda>
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 481, in compile
return self._compiler(dialect, bind=bind, **kw)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 487, in _compiler
return dialect.statement_compiler(dialect, self, **kw)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 592, in __init__
Compiled.__init__(self, dialect, statement, **kwargs)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 322, in __init__
self.string = self.process(self.statement, **compile_kwargs)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 352, in process
return obj._compiler_dispatch(self, **kwargs)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/ext/compiler.py", line 441, in <lambda>
lambda *arg, **kw: existing(*arg, **kw),
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/ext/compiler.py", line 486, in __call__
return fn(element, compiler, **kw)
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/ext/compiler.py", line 432, in _wrap_existing_dispatch
from_=uce,
File "/root/git/feed_test_results/venv/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 182, in raise_
raise exception
sqlalchemy.exc.CompileError: <class '__main__.combine_date_time'> construct has no default compilation handler.

# Fixed code
def compiles(class_, *specs):
    """Register a function as a compiler for a
    given :class:`_expression.ClauseElement` type."""

    def decorate(fn):
        # get an existing @compiles handler
        existing = class_.__dict__.get("_compiler_dispatcher", None)

        # get the original handler.  All ClauseElement classes have one
        # of these, but some TypeEngine classes will not.
        existing_dispatch = getattr(class_, "_compiler_dispatch", None)

        if not existing:
            existing = _dispatcher()

            if existing_dispatch:

                def _wrap_existing_dispatch(element, compiler, **kw):
                    try:
                        return existing_dispatch(element, compiler, **kw)
                    except exc.UnsupportedCompilationError as uce:
                        util.raise_(
                            exc.UnsupportedCompilationError(
                                compiler,
                                type(element),
                                message="%s construct has no default "
                                "compilation handler." % type(element),
                            ),
                            from_=uce,
                        )

                existing.specs["default"] = _wrap_existing_dispatch

            # TODO: why is the lambda needed ?
            setattr(
                class_,
                "_compiler_dispatch",
                lambda *arg, **kw: existing(*arg, **kw),
            )
            setattr(class_, "_compiler_dispatcher", existing)

        if specs:
            for s in specs:
                existing.specs[s] = fn

        else:
            existing.specs["default"] = fn
        return fn

    return decorate