18 """abstract views and templates classes for CubicWeb web client""" |
18 """abstract views and templates classes for CubicWeb web client""" |
19 |
19 |
20 __docformat__ = "restructuredtext en" |
20 __docformat__ = "restructuredtext en" |
21 _ = unicode |
21 _ = unicode |
22 |
22 |
|
23 import types, new |
23 from cStringIO import StringIO |
24 from cStringIO import StringIO |
24 from warnings import warn |
25 from warnings import warn |
25 |
26 |
26 from logilab.common.deprecation import deprecated |
27 from logilab.common.deprecation import deprecated |
27 from logilab.mtconverter import xml_escape |
28 from logilab.mtconverter import xml_escape |
541 class Adapter(AppObject): |
542 class Adapter(AppObject): |
542 """base class for adapters""" |
543 """base class for adapters""" |
543 __registry__ = 'adapters' |
544 __registry__ = 'adapters' |
544 |
545 |
545 |
546 |
546 class EntityAdapter(Adapter): |
|
547 """base class for entity adapters (eg adapt an entity to an interface)""" |
|
548 def __init__(self, _cw, **kwargs): |
|
549 try: |
|
550 self.entity = kwargs.pop('entity') |
|
551 except KeyError: |
|
552 self.entity = kwargs['rset'].get_entity(kwargs.get('row') or 0, |
|
553 kwargs.get('col') or 0) |
|
554 Adapter.__init__(self, _cw, **kwargs) |
|
555 |
|
556 |
|
557 def implements_adapter_compat(iface): |
547 def implements_adapter_compat(iface): |
558 def _pre39_compat(func): |
548 def _pre39_compat(func): |
559 def decorated(self, *args, **kwargs): |
549 def decorated(self, *args, **kwargs): |
560 entity = self.entity |
550 entity = self.entity |
561 if hasattr(entity, func.__name__): |
551 if hasattr(entity, func.__name__): |
566 member = getattr(entity, func.__name__) |
556 member = getattr(entity, func.__name__) |
567 if callable(member): |
557 if callable(member): |
568 return member(*args, **kwargs) |
558 return member(*args, **kwargs) |
569 return member |
559 return member |
570 return func(self, *args, **kwargs) |
560 return func(self, *args, **kwargs) |
|
561 decorated.decorated = func |
571 return decorated |
562 return decorated |
572 return _pre39_compat |
563 return _pre39_compat |
|
564 |
|
565 |
|
566 def unwrap_adapter_compat(cls): |
|
567 parent = cls.__bases__[0] |
|
568 for member_name in dir(parent): |
|
569 member = getattr(parent, member_name) |
|
570 if isinstance(member, types.MethodType) and hasattr(member.im_func, 'decorated') and not member_name in cls.__dict__: |
|
571 method = new.instancemethod(member.im_func.decorated, None, cls) |
|
572 setattr(cls, member_name, method) |
|
573 |
|
574 |
|
575 class auto_unwrap_bw_compat(type): |
|
576 def __new__(mcs, name, bases, classdict): |
|
577 cls = type.__new__(mcs, name, bases, classdict) |
|
578 if not classdict.get('__needs_bw_compat__'): |
|
579 unwrap_adapter_compat(cls) |
|
580 return cls |
|
581 |
|
582 |
|
583 class EntityAdapter(Adapter): |
|
584 """base class for entity adapters (eg adapt an entity to an interface)""" |
|
585 __metaclass__ = auto_unwrap_bw_compat |
|
586 def __init__(self, _cw, **kwargs): |
|
587 try: |
|
588 self.entity = kwargs.pop('entity') |
|
589 except KeyError: |
|
590 self.entity = kwargs['rset'].get_entity(kwargs.get('row') or 0, |
|
591 kwargs.get('col') or 0) |
|
592 Adapter.__init__(self, _cw, **kwargs) |