will expunge the object if the cascade also includes
"delete-orphan", or will simply detach it otherwise.
[ticket:1754]
-
+
+- ext
+ - the compiler extension now allows @compiles decorators
+ on base classes that extend to child classes, @compiles
+ decorators on child classes that aren't broken by a
+ @compiles decorator on the base class.
+
0.6beta3
========
def compiles(class_, *specs):
def decorate(fn):
- existing = getattr(class_, '_compiler_dispatcher', None)
+ existing = class_.__dict__.get('_compiler_dispatcher', None)
if not existing:
existing = _dispatcher()
# set up an optimized visit dispatch function
# for use by the compiler
- visit_name = cls.__visit_name__
- if isinstance(visit_name, str):
- getter = operator.attrgetter("visit_%s" % visit_name)
- def _compiler_dispatch(self, visitor, **kw):
- return getter(visitor)(self, **kw)
- else:
- def _compiler_dispatch(self, visitor, **kw):
- return getattr(visitor, 'visit_%s' % self.__visit_name__)(self, **kw)
-
- cls._compiler_dispatch = _compiler_dispatch
+ if '__visit_name__' in cls.__dict__:
+ visit_name = cls.__visit_name__
+ if isinstance(visit_name, str):
+ getter = operator.attrgetter("visit_%s" % visit_name)
+ def _compiler_dispatch(self, visitor, **kw):
+ return getter(visitor)(self, **kw)
+ else:
+ def _compiler_dispatch(self, visitor, **kw):
+ return getattr(visitor, 'visit_%s' % self.__visit_name__)(self, **kw)
+
+ cls._compiler_dispatch = _compiler_dispatch
super(VisitableType, cls).__init__(clsname, bases, clsdict)
"timezone('utc', current_timestamp)",
dialect=postgresql.dialect()
)
-
+
+ def test_subclasses_one(self):
+ class Base(FunctionElement):
+ name = 'base'
+
+ class Sub1(Base):
+ name = 'sub1'
+
+ class Sub2(Base):
+ name = 'sub2'
+
+ @compiles(Base)
+ def visit_base(element, compiler, **kw):
+ return element.name
+
+ @compiles(Sub1)
+ def visit_base(element, compiler, **kw):
+ return "FOO" + element.name
+
+ self.assert_compile(
+ select([Sub1(), Sub2()]),
+ 'SELECT FOOsub1, sub2',
+ use_default_dialect=True
+ )
+
+ def test_subclasses_two(self):
+ class Base(FunctionElement):
+ name = 'base'
+ class Sub1(Base):
+ name = 'sub1'
+
+ @compiles(Base)
+ def visit_base(element, compiler, **kw):
+ return element.name
+
+ class Sub2(Base):
+ name = 'sub2'
+
+ class SubSub1(Sub1):
+ name = 'subsub1'
+
+ self.assert_compile(
+ select([Sub1(), Sub2(), SubSub1()]),
+ 'SELECT sub1, sub2, subsub1',
+ use_default_dialect=True
+ )
+
+ @compiles(Sub1)
+ def visit_base(element, compiler, **kw):
+ return "FOO" + element.name
+
+ self.assert_compile(
+ select([Sub1(), Sub2(), SubSub1()]),
+ 'SELECT FOOsub1, sub2, FOOsubsub1',
+ use_default_dialect=True
+ )
\ No newline at end of file