[selectors] provide a new, optimized, is_instance selector that should at some point replace implements (along with the adaptable selector)
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 05 Jul 2010 12:04:32 +0200
changeset 5877 0c7b7b76a84f
parent 5876 e77aa963fb19
child 5878 8d1ca4150397
[selectors] provide a new, optimized, is_instance selector that should at some point replace implements (along with the adaptable selector)
devtools/test/data/views.py
entities/adapters.py
hooks/integrity.py
hooks/metadata.py
hooks/notification.py
hooks/syncschema.py
hooks/syncsession.py
hooks/workflow.py
selectors.py
server/hook.py
server/test/unittest_fti.py
server/test/unittest_hook.py
server/test/unittest_repository.py
server/test/unittest_storage.py
sobjects/test/data/sobjects/__init__.py
test/unittest_selectors.py
web/test/unittest_viewselector.py
web/views/actions.py
web/views/bookmark.py
web/views/cwproperties.py
web/views/cwuser.py
web/views/editcontroller.py
web/views/editforms.py
web/views/emailaddress.py
web/views/formrenderers.py
web/views/ibreadcrumbs.py
web/views/idownloadable.py
web/views/igeocodable.py
web/views/massmailing.py
web/views/schema.py
web/views/startup.py
web/views/tabs.py
web/views/vcard.py
web/views/workflow.py
web/views/xbel.py
web/views/xmlrss.py
--- a/devtools/test/data/views.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/devtools/test/data/views.py	Mon Jul 05 12:04:32 2010 +0200
@@ -15,12 +15,10 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""only for unit tests !
-
-"""
+"""only for unit tests !"""
 
 from cubicweb.view import EntityView
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 
 HTML_PAGE = u"""<html>
   <body>
@@ -31,7 +29,7 @@
 
 class SimpleView(EntityView):
     __regid__ = 'simple'
-    __select__ = implements('Bug',)
+    __select__ = is_instance('Bug',)
 
     def call(self, **kwargs):
         self.cell_call(0, 0)
@@ -41,7 +39,7 @@
 
 class RaisingView(EntityView):
     __regid__ = 'raising'
-    __select__ = implements('Bug',)
+    __select__ = is_instance('Bug',)
 
     def cell_call(self, row, col):
         raise ValueError()
--- a/entities/adapters.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/entities/adapters.py	Mon Jul 05 12:04:32 2010 +0200
@@ -28,7 +28,7 @@
 from logilab.common.decorators import cached
 
 from cubicweb.view import EntityAdapter, implements_adapter_compat
-from cubicweb.selectors import implements, relation_possible
+from cubicweb.selectors import implements, is_instance, relation_possible
 from cubicweb.interfaces import IDownloadable, ITree, IProgress, IMileStone
 
 
@@ -67,7 +67,7 @@
 
 class INotifiableAdapter(EntityAdapter):
     __regid__ = 'INotifiable'
-    __select__ = implements('Any')
+    __select__ = is_instance('Any')
 
     @implements_adapter_compat('INotifiableAdapter')
     def notification_references(self, view):
@@ -85,7 +85,7 @@
 
 class IFTIndexableAdapter(EntityAdapter):
     __regid__ = 'IFTIndexable'
-    __select__ = implements('Any')
+    __select__ = is_instance('Any')
 
     def fti_containers(self, _done=None):
         if _done is None:
--- a/hooks/integrity.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/hooks/integrity.py	Mon Jul 05 12:04:32 2010 +0200
@@ -27,7 +27,7 @@
 
 from cubicweb import ValidationError
 from cubicweb.schema import RQLConstraint, RQLUniqueConstraint
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.uilib import soup2xhtml
 from cubicweb.server import hook
 from cubicweb.server.hook import set_operation
@@ -253,7 +253,7 @@
     """delete the composed of a composite relation when this relation is deleted
     """
     __regid__ = 'checkownersgroup'
-    __select__ = IntegrityHook.__select__ & implements('CWGroup')
+    __select__ = IntegrityHook.__select__ & is_instance('CWGroup')
     events = ('before_delete_entity', 'before_update_entity')
 
     def __call__(self):
@@ -293,7 +293,7 @@
 class StripCWUserLoginHook(IntegrityHook):
     """ensure user logins are stripped"""
     __regid__ = 'stripuserlogin'
-    __select__ = IntegrityHook.__select__ & implements('CWUser')
+    __select__ = IntegrityHook.__select__ & is_instance('CWUser')
     events = ('before_add_entity', 'before_update_entity',)
 
     def __call__(self):
--- a/hooks/metadata.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/hooks/metadata.py	Mon Jul 05 12:04:32 2010 +0200
@@ -21,7 +21,7 @@
 
 from datetime import datetime
 
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.server import hook
 from cubicweb.server.utils import eschema_eid
 
@@ -140,7 +140,7 @@
 class FixUserOwnershipHook(MetaDataHook):
     """when a user has been created, add owned_by relation on itself"""
     __regid__ = 'fixuserowner'
-    __select__ = MetaDataHook.__select__ & implements('CWUser')
+    __select__ = MetaDataHook.__select__ & is_instance('CWUser')
     events = ('after_add_entity',)
 
     def __call__(self):
--- a/hooks/notification.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/hooks/notification.py	Mon Jul 05 12:04:32 2010 +0200
@@ -22,7 +22,7 @@
 
 from logilab.common.textutils import normalize_text
 
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.server import hook
 from cubicweb.sobjects.supervising import SupervisionMailOp
 
@@ -49,7 +49,7 @@
 class StatusChangeHook(NotificationHook):
     """notify when a workflowable entity has its state modified"""
     __regid__ = 'notifystatuschange'
-    __select__ = NotificationHook.__select__ & implements('TrInfo')
+    __select__ = NotificationHook.__select__ & is_instance('TrInfo')
     events = ('after_add_entity',)
 
     def __call__(self):
--- a/hooks/syncschema.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/hooks/syncschema.py	Mon Jul 05 12:04:32 2010 +0200
@@ -33,7 +33,7 @@
 from logilab.common.testlib import mock_object
 
 from cubicweb import ValidationError
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.schema import (META_RTYPES, VIRTUAL_RTYPES, CONSTRAINTS,
                              ETYPE_NAME_MAP, display_name)
 from cubicweb.server import hook, schemaserial as ss
@@ -809,7 +809,7 @@
     * instantiate an operation to delete the entity type on commit
     """
     __regid__ = 'syncdelcwetype'
-    __select__ = SyncSchemaHook.__select__ & implements('CWEType')
+    __select__ = SyncSchemaHook.__select__ & is_instance('CWEType')
     events = ('before_delete_entity',)
 
     def __call__(self):
@@ -914,7 +914,7 @@
     * instantiate an operation to delete the relation type on commit
     """
     __regid__ = 'syncdelcwrtype'
-    __select__ = SyncSchemaHook.__select__ & implements('CWRType')
+    __select__ = SyncSchemaHook.__select__ & is_instance('CWRType')
     events = ('before_delete_entity',)
 
     def __call__(self):
@@ -1032,7 +1032,7 @@
 
 class AfterAddCWAttributeHook(SyncSchemaHook):
     __regid__ = 'syncaddcwattribute'
-    __select__ = SyncSchemaHook.__select__ & implements('CWAttribute')
+    __select__ = SyncSchemaHook.__select__ & is_instance('CWAttribute')
     events = ('after_add_entity',)
 
     def __call__(self):
@@ -1041,7 +1041,7 @@
 
 class AfterAddCWRelationHook(AfterAddCWAttributeHook):
     __regid__ = 'syncaddcwrelation'
-    __select__ = SyncSchemaHook.__select__ & implements('CWRelation')
+    __select__ = SyncSchemaHook.__select__ & is_instance('CWRelation')
 
     def __call__(self):
         SourceDbCWRelationAdd(self._cw, entity=self.entity)
@@ -1049,7 +1049,7 @@
 
 class AfterUpdateCWRDefHook(SyncSchemaHook):
     __regid__ = 'syncaddcwattribute'
-    __select__ = SyncSchemaHook.__select__ & implements('CWAttribute',
+    __select__ = SyncSchemaHook.__select__ & is_instance('CWAttribute',
                                                         'CWRelation')
     events = ('before_update_entity',)
 
@@ -1081,7 +1081,7 @@
 
 class AfterAddCWConstraintHook(SyncSchemaHook):
     __regid__ = 'syncaddcwconstraint'
-    __select__ = SyncSchemaHook.__select__ & implements('CWConstraint')
+    __select__ = SyncSchemaHook.__select__ & is_instance('CWConstraint')
     events = ('after_add_entity', 'after_update_entity')
 
     def __call__(self):
--- a/hooks/syncsession.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/hooks/syncsession.py	Mon Jul 05 12:04:32 2010 +0200
@@ -22,7 +22,7 @@
 
 from yams.schema import role_name
 from cubicweb import UnknownProperty, ValidationError, BadConnectionId
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.server import hook
 
 
@@ -108,7 +108,7 @@
 
 class CloseDeletedUserSessionsHook(SyncSessionHook):
     __regid__ = 'closession'
-    __select__ = SyncSessionHook.__select__ & implements('CWUser')
+    __select__ = SyncSessionHook.__select__ & is_instance('CWUser')
     events = ('after_delete_entity',)
 
     def __call__(self):
@@ -152,7 +152,7 @@
 
 class AddCWPropertyHook(SyncSessionHook):
     __regid__ = 'addcwprop'
-    __select__ = SyncSessionHook.__select__ & implements('CWProperty')
+    __select__ = SyncSessionHook.__select__ & is_instance('CWProperty')
     events = ('after_add_entity',)
 
     def __call__(self):
--- a/hooks/workflow.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/hooks/workflow.py	Mon Jul 05 12:04:32 2010 +0200
@@ -24,7 +24,7 @@
 from yams.schema import role_name
 
 from cubicweb import RepositoryError, ValidationError
-from cubicweb.selectors import implements, adaptable
+from cubicweb.selectors import is_instance, adaptable
 from cubicweb.server import hook
 
 
@@ -177,7 +177,7 @@
     * by_transition or to_state (managers only) inlined relation is set
     """
     __regid__ = 'wffiretransition'
-    __select__ = WorkflowHook.__select__ & implements('TrInfo')
+    __select__ = WorkflowHook.__select__ & is_instance('TrInfo')
     events = ('before_add_entity',)
 
     def __call__(self):
@@ -273,7 +273,7 @@
 class FiredTransitionHook(WorkflowHook):
     """change related entity state"""
     __regid__ = 'wffiretransition'
-    __select__ = WorkflowHook.__select__ & implements('TrInfo')
+    __select__ = WorkflowHook.__select__ & is_instance('TrInfo')
     events = ('after_add_entity',)
 
     def __call__(self):
--- a/selectors.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/selectors.py	Mon Jul 05 12:04:32 2010 +0200
@@ -244,31 +244,6 @@
         return super(PartialSelectorMixIn, self).__call__(cls, *args, **kwargs)
 
 
-class ImplementsMixIn(object):
-    """mix-in class for selectors checking implemented interfaces of something
-    """
-    def __init__(self, *expected_ifaces, **kwargs):
-        super(ImplementsMixIn, self).__init__(**kwargs)
-        self.expected_ifaces = expected_ifaces
-
-    def __str__(self):
-        return '%s(%s)' % (self.__class__.__name__,
-                           ','.join(str(s) for s in self.expected_ifaces))
-
-    def score_interfaces(self, req, cls_or_inst, cls):
-        score = 0
-        etypesreg = req.vreg['etypes']
-        for iface in self.expected_ifaces:
-            if isinstance(iface, basestring):
-                # entity type
-                try:
-                    iface = etypesreg.etype_class(iface)
-                except KeyError:
-                    continue # entity type not in the schema
-            score += score_interface(etypesreg, cls_or_inst, cls, iface)
-        return score
-
-
 class EClassSelector(Selector):
     """abstract class for selectors working on *entity class(es)* specified
     explicitly or found of the result set.
@@ -411,7 +386,7 @@
     """Take a list of expected values as initializer argument and store them
     into the :attr:`expected` set attribute.
 
-    You should implements the :meth:`_get_value(cls, req, **kwargs)` method
+    You should implement the :meth:`_get_value(cls, req, **kwargs)` method
     which should return the value for the given context. The selector will then
     return 1 if the value is expected, else 0.
     """
@@ -484,8 +459,8 @@
       (usually entities) should be adaptable. One of them should be selectable
       when multiple identifiers are given.
     """
-    # implementing an interface takes precedence other special Any interface,
-    # hence return 2 (implements('Any') score is 1)
+    # being adaptable to an interface takes precedence other is_instance('Any'),
+    # hence return 2 (is_instance('Any') score is 1)
     selectable_score = 2
     def __init__(self, *regids):
         super(adaptable, self).__init__('adapters', *regids)
@@ -664,7 +639,7 @@
 class non_final_entity(EClassSelector):
     """Return 1 for entity of a non final entity type(s). Remember, "final"
     entity types are String, Int, etc... This is equivalent to
-    `implements('Any')` but more optimized.
+    `is_instance('Any')` but more optimized.
 
     See :class:`~cubicweb.selectors.EClassSelector` documentation for entity
     class lookup / score rules according to the input context.
@@ -678,7 +653,7 @@
         return 1 # necessarily true if we're there
 
 
-class implements(ImplementsMixIn, EClassSelector):
+class implements(EClassSelector):
     """Return non-zero score for entity that are of the given type(s) or
     implements at least one of the given interface(s). If multiple arguments are
     given, matching one of them is enough.
@@ -692,14 +667,100 @@
     .. note:: when interface is an entity class, the score will reflect class
               proximity so the most specific object will be selected.
 
-    .. note:: with cubicweb >= 3.9, you should use adapters instead of
-              interface, so no interface should be given to this selector. Use
-              :class:`adaptable` instead.
+    .. note:: deprecated in cubicweb >= 3.9, use either
+              :class:`~cubicweb.selectors.is_instance` or
+              :class:`~cubicweb.selectors.adaptable`.
     """
 
+    def __init__(self, *expected_ifaces, **kwargs):
+        super(implements, self).__init__(**kwargs)
+        self.expected_ifaces = expected_ifaces
+        warn('[3.9] implements selector is deprecated, use either is_instance '
+             'or adaptable', DeprecationWarning, stacklevel=1)
+
+    def __str__(self):
+        return '%s(%s)' % (self.__class__.__name__,
+                           ','.join(str(s) for s in self.expected_ifaces))
+
     def score_class(self, eclass, req):
         return self.score_interfaces(req, eclass, eclass)
 
+    def score_interfaces(self, req, cls_or_inst, cls):
+        score = 0
+        etypesreg = req.vreg['etypes']
+        for iface in self.expected_ifaces:
+            if isinstance(iface, basestring):
+                # entity type
+                try:
+                    iface = etypesreg.etype_class(iface)
+                except KeyError:
+                    continue # entity type not in the schema
+            score += score_interface(etypesreg, cls_or_inst, cls, iface)
+        return score
+
+
+class is_instance(EClassSelector):
+    """Return non-zero score for entity that is an instance of the one of given
+    type(s). If multiple arguments are given, matching one of them is enough.
+
+    Entity types should be given as string, the corresponding class will be
+    fetched from the registry at selection time.
+
+    See :class:`~cubicweb.selectors.EClassSelector` documentation for entity
+    class lookup / score rules according to the input context.
+
+    .. note:: the score will reflect class proximity so the most specific object
+              will be selected.
+    """
+
+    def __init__(self, *expected_etypes, **kwargs):
+        super(is_instance, self).__init__(**kwargs)
+        self.expected_etypes = expected_etypes
+        for etype in self.expected_etypes:
+            assert isinstance(etype, basestring), etype
+
+    def __str__(self):
+        return '%s(%s)' % (self.__class__.__name__,
+                           ','.join(str(s) for s in self.expected_etypes))
+
+    def score_class(self, eclass, req):
+        return self.score_etypes(req, eclass, eclass)
+
+    def score_etypes(self, req, cls_or_inst, cls):
+        # cache on vreg to avoid reloading issues
+        try:
+            cache = req.vreg.__is_instance_cache
+        except AttributeError:
+            cache = req.vreg.__is_instance_cache = {}
+        try:
+            expected_eclasses = cache[self]
+        except KeyError:
+            # turn list of entity types as string into a list of
+            #  (entity class, parent classes)
+            etypesreg = req.vreg['etypes']
+            expected_eclasses = cache[self] = []
+            for etype in self.expected_etypes:
+                try:
+                    expected_eclasses.append(
+                        (etypesreg.etype_class(etype),
+                         etypesreg.parent_classes(etype))
+                        )
+                except KeyError:
+                    continue # entity type not in the schema
+        score = 0
+        for iface, parents in expected_eclasses:
+            # adjust score according to class proximity
+            if iface is cls:
+                score += len(parents) + 4
+            elif iface is parents[-1]: # Any
+                score += 1
+            else:
+                for index, basecls in enumerate(reversed(parents[:-1])):
+                    if iface is basecls:
+                        score += index + 3
+                        break
+        return score
+
 
 class score_entity(EntitySelector):
     """Return score according to an arbitrary function given as argument which
@@ -1202,18 +1263,15 @@
         return len(self.expected)
 
 
-class specified_etype_implements(implements):
+class specified_etype_implements(is_instance):
     """Return non-zero score if the entity type specified by an 'etype' key
     searched in (by priority) input context kwargs and request form parameters
     match a known entity type (case insensitivly), and it's associated entity
-    class is of one of the type(s) given to the initializer or implements at
-    least one of the given interfaces. If multiple arguments are given, matching
-    one of them is enough.
+    class is of one of the type(s) given to the initializer. If multiple
+    arguments are given, matching one of them is enough.
 
-    Entity types should be given as string, the corresponding class will be
-    fetched from the entity types registry at selection time.
-
-    .. note:: when interface is an entity class, the score will reflect class
+    .. note:: as with :class:`~cubicweb.selectors.is_instance`, entity types
+              should be given as string and the score will reflect class
               proximity so the most specific object will be selected.
 
     This selector is usually used by views holding entity creation forms (since
@@ -1292,7 +1350,7 @@
 
 ## deprecated stuff ############################################################
 
-entity_implements = class_renamed('entity_implements', implements)
+entity_implements = class_renamed('entity_implements', is_instance)
 
 class _but_etype(EntitySelector):
     """accept if the given entity types are not found in the result set.
@@ -1310,7 +1368,7 @@
             return 0
         return 1
 
-but_etype = class_renamed('but_etype', _but_etype, 'use ~implements(*etypes) instead')
+but_etype = class_renamed('but_etype', _but_etype, 'use ~is_instance(*etypes) instead')
 
 
 # XXX deprecated the one_* variants of selectors below w/ multi_xxx(nb=1)?
--- a/server/hook.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/server/hook.py	Mon Jul 05 12:04:32 2010 +0200
@@ -63,7 +63,7 @@
 from cubicweb import RegistryNotFound
 from cubicweb.cwvreg import CWRegistry, VRegistry
 from cubicweb.selectors import (objectify_selector, lltrace, ExpectedValueSelector,
-                                implements)
+                                is_instance)
 from cubicweb.appobject import AppObject
 from cubicweb.server.session import security_enabled
 
@@ -246,7 +246,7 @@
                 if ertype.islower():
                     rtypes.append(ertype)
                 else:
-                    cls.__select__ = cls.__select__ & implements(ertype)
+                    cls.__select__ = cls.__select__ & is_instance(ertype)
             if rtypes:
                 cls.__select__ = cls.__select__ & match_rtype(*rtypes)
         return cls
@@ -262,7 +262,7 @@
     def __call__(self):
         if hasattr(self, 'call'):
             cls = self.__class__
-            warn('[3.6] %s.%s: call is deprecated, implements __call__'
+            warn('[3.6] %s.%s: call is deprecated, implement __call__'
                  % (cls.__module__, cls.__name__), DeprecationWarning)
             if self.event.endswith('_relation'):
                 self.call(self._cw, self.eidfrom, self.rtype, self.eidto)
--- a/server/test/unittest_fti.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/server/test/unittest_fti.py	Mon Jul 05 12:04:32 2010 +0200
@@ -2,7 +2,7 @@
 
 from cubicweb.devtools import ApptestConfiguration
 from cubicweb.devtools.testlib import CubicWebTC
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.entities.adapters import IFTIndexableAdapter
 
 class PostgresFTITC(CubicWebTC):
@@ -23,7 +23,7 @@
 
     def test_attr_weight(self):
         class CardIFTIndexableAdapter(IFTIndexableAdapter):
-            __select__ = implements('Card')
+            __select__ = is_instance('Card')
             attr_weight = {'title': 'A'}
         with self.temporary_appobjects(CardIFTIndexableAdapter):
             req = self.request()
@@ -40,7 +40,7 @@
 
     def test_entity_weight(self):
         class PersonneIFTIndexableAdapter(IFTIndexableAdapter):
-            __select__ = implements('Personne')
+            __select__ = is_instance('Personne')
             entity_weight = 2.0
         with self.temporary_appobjects(PersonneIFTIndexableAdapter):
             req = self.request()
--- a/server/test/unittest_hook.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/server/test/unittest_hook.py	Mon Jul 05 12:04:32 2010 +0200
@@ -25,7 +25,6 @@
 
 from cubicweb.devtools import TestServerConfiguration
 from cubicweb.devtools.testlib import CubicWebTC
-from cubicweb.selectors import implements
 from cubicweb.server import hook
 from cubicweb.hooks import integrity, syncschema
 
--- a/server/test/unittest_repository.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/server/test/unittest_repository.py	Mon Jul 05 12:04:32 2010 +0200
@@ -33,7 +33,7 @@
 
 from cubicweb import (BadConnectionId, RepositoryError, ValidationError,
                       UnknownEid, AuthenticationError)
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.schema import CubicWebSchema, RQLConstraint
 from cubicweb.dbapi import connect, multiple_connections_unfix
 from cubicweb.devtools.testlib import CubicWebTC
@@ -387,7 +387,7 @@
         # local hook
         class DummyBeforeHook(Hook):
             __regid__ = 'dummy-before-hook'
-            __select__ = Hook.__select__ & implements('EmailAddress')
+            __select__ = Hook.__select__ & is_instance('EmailAddress')
             events = ('before_update_entity',)
             def __call__(self):
                 # safety belt: avoid potential infinite recursion if the test
@@ -408,7 +408,7 @@
         # local hook
         class DummyBeforeHook(Hook):
             __regid__ = 'dummy-before-hook'
-            __select__ = Hook.__select__ & implements('EmailAddress')
+            __select__ = Hook.__select__ & is_instance('EmailAddress')
             events = ('before_add_entity',)
             def __call__(self):
                 # set_attributes is forbidden within before_add_entity()
@@ -427,7 +427,7 @@
         class DummyBeforeHook(Hook):
             _test = self # keep reference to test instance
             __regid__ = 'dummy-before-hook'
-            __select__ = Hook.__select__ & implements('Affaire')
+            __select__ = Hook.__select__ & is_instance('Affaire')
             events = ('before_update_entity',)
             def __call__(self):
                 # invoiced attribute shouldn't be considered "edited" before the hook
--- a/server/test/unittest_storage.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/server/test/unittest_storage.py	Mon Jul 05 12:04:32 2010 +0200
@@ -27,13 +27,13 @@
 import tempfile
 
 from cubicweb import Binary, QueryError
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.server.sources import storages
 from cubicweb.server.hook import Hook, Operation
 
 class DummyBeforeHook(Hook):
     __regid__ = 'dummy-before-hook'
-    __select__ = Hook.__select__ & implements('File')
+    __select__ = Hook.__select__ & is_instance('File')
     events = ('before_add_entity',)
 
     def __call__(self):
@@ -42,7 +42,7 @@
 
 class DummyAfterHook(Hook):
     __regid__ = 'dummy-after-hook'
-    __select__ = Hook.__select__ & implements('File')
+    __select__ = Hook.__select__ & is_instance('File')
     events = ('after_add_entity',)
 
     def __call__(self):
--- a/sobjects/test/data/sobjects/__init__.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/sobjects/test/data/sobjects/__init__.py	Mon Jul 05 12:04:32 2010 +0200
@@ -15,11 +15,9 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
 
-"""
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.sobjects.notification import StatusChangeMixIn, NotificationView
 
 class UserStatusChangeView(StatusChangeMixIn, NotificationView):
-    __select__ = NotificationView.__select__ & implements('CWUser')
+    __select__ = NotificationView.__select__ & is_instance('CWUser')
--- a/test/unittest_selectors.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/test/unittest_selectors.py	Mon Jul 05 12:04:32 2010 +0200
@@ -22,7 +22,7 @@
 from cubicweb import Binary
 from cubicweb.devtools.testlib import CubicWebTC
 from cubicweb.appobject import Selector, AndSelector, OrSelector
-from cubicweb.selectors import implements, adaptable, match_user_groups
+from cubicweb.selectors import is_instance, adaptable, match_user_groups
 from cubicweb.interfaces import IDownloadable
 from cubicweb.web import action
 
@@ -92,12 +92,12 @@
         self.assertEquals(selector(None), 2)
 
     def test_search_selectors(self):
-        sel = implements('something')
-        self.assertIs(sel.search_selector(implements), sel)
+        sel = is_instance('something')
+        self.assertIs(sel.search_selector(is_instance), sel)
         csel = AndSelector(sel, Selector())
-        self.assertIs(csel.search_selector(implements), sel)
+        self.assertIs(csel.search_selector(is_instance), sel)
         csel = AndSelector(Selector(), sel)
-        self.assertIs(csel.search_selector(implements), sel)
+        self.assertIs(csel.search_selector(is_instance), sel)
 
     def test_inplace_and(self):
         selector = _1_()
@@ -141,15 +141,15 @@
         req = self.request()
         f = req.create_entity('File', data_name=u'hop.txt', data=Binary('hop'))
         rset = f.as_rset()
-        anyscore = implements('Any')(f.__class__, req, rset=rset)
+        anyscore = is_instance('Any')(f.__class__, req, rset=rset)
         idownscore = adaptable('IDownloadable')(f.__class__, req, rset=rset)
         self.failUnless(idownscore > anyscore, (idownscore, anyscore))
-        filescore = implements('File')(f.__class__, req, rset=rset)
+        filescore = is_instance('File')(f.__class__, req, rset=rset)
         self.failUnless(filescore > idownscore, (filescore, idownscore))
 
     def test_etype_inheritance_no_yams_inheritance(self):
         cls = self.vreg['etypes'].etype_class('Personne')
-        self.failIf(implements('Societe').score_class(cls, self.request()))
+        self.failIf(is_instance('Societe').score_class(cls, self.request()))
 
 
 class MatchUserGroupsTC(CubicWebTC):
--- a/web/test/unittest_viewselector.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/test/unittest_viewselector.py	Mon Jul 05 12:04:32 2010 +0200
@@ -22,7 +22,7 @@
 
 from cubicweb.devtools.testlib import CubicWebTC
 from cubicweb import CW_SOFTWARE_ROOT as BASE, Binary, UnknownProperty
-from cubicweb.selectors import (match_user_groups, implements,
+from cubicweb.selectors import (match_user_groups, is_instance,
                                 specified_etype_implements, rql_condition,
                                 traced_selection)
 from cubicweb.web import NoSelectableObject
@@ -476,7 +476,7 @@
 
 class CWETypeRQLAction(Action):
     __regid__ = 'testaction'
-    __select__ = implements('CWEType') & rql_condition('X name "CWEType"')
+    __select__ = is_instance('CWEType') & rql_condition('X name "CWEType"')
     title = 'bla'
 
 class RQLActionTC(ViewSelectorTC):
--- a/web/views/actions.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/actions.py	Mon Jul 05 12:04:32 2010 +0200
@@ -30,7 +30,7 @@
     one_line_rset, multi_lines_rset, one_etype_rset, relation_possible,
     nonempty_rset, non_final_entity,
     authenticated_user, match_user_groups, match_search_state,
-    has_permission, has_add_permission, implements, debug_mode,
+    has_permission, has_add_permission, is_instance, debug_mode,
     )
 from cubicweb.web import uicfg, controller, action
 from cubicweb.web.views import linksearch_select_url, vid_from_rset
@@ -323,7 +323,7 @@
     """when displaying the schema of a CWEType, offer to list entities of that type
     """
     __regid__ = 'entitiesoftype'
-    __select__ = one_line_rset() & implements('CWEType')
+    __select__ = one_line_rset() & is_instance('CWEType')
     category = 'mainactions'
     order = 40
 
--- a/web/views/bookmark.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/bookmark.py	Mon Jul 05 12:04:32 2010 +0200
@@ -23,7 +23,7 @@
 from logilab.mtconverter import xml_escape
 
 from cubicweb import Unauthorized
-from cubicweb.selectors import implements, one_line_rset
+from cubicweb.selectors import is_instance, one_line_rset
 from cubicweb.web.htmlwidgets import BoxWidget, BoxMenu, RawBoxItem
 from cubicweb.web import action, box, uicfg, formwidgets as fw
 from cubicweb.web.views import primary
@@ -43,7 +43,7 @@
 
 class FollowAction(action.Action):
     __regid__ = 'follow'
-    __select__ = one_line_rset() & implements('Bookmark')
+    __select__ = one_line_rset() & is_instance('Bookmark')
 
     title = _('follow')
     category = 'mainactions'
@@ -53,7 +53,7 @@
 
 
 class BookmarkPrimaryView(primary.PrimaryView):
-    __select__ = implements('Bookmark')
+    __select__ = is_instance('Bookmark')
 
     def cell_call(self, row, col):
         """the primary view for bookmark entity"""
--- a/web/views/cwproperties.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/cwproperties.py	Mon Jul 05 12:04:32 2010 +0200
@@ -26,7 +26,7 @@
 from logilab.common.decorators import cached
 
 from cubicweb import UnknownProperty
-from cubicweb.selectors import (one_line_rset, none_rset, implements,
+from cubicweb.selectors import (one_line_rset, none_rset, is_instance,
                                 match_user_groups, objectify_selector,
                                 logged_user_in_rset)
 from cubicweb.view import StartupView
@@ -74,7 +74,7 @@
 
 
 class CWPropertyPrimaryView(primary.PrimaryView):
-    __select__ = implements('CWProperty')
+    __select__ = is_instance('CWProperty')
     skip_none = False
 
 
@@ -243,7 +243,7 @@
     __select__ = (
         (none_rset() & match_user_groups('users','managers'))
         | (one_line_rset() & match_user_groups('users') & logged_user_in_rset())
-        | (one_line_rset() & match_user_groups('managers') & implements('CWUser'))
+        | (one_line_rset() & match_user_groups('managers') & is_instance('CWUser'))
         )
 
     title = _('preferences')
@@ -397,7 +397,7 @@
 
 
 class CWPropertyIEditControlAdapter(editcontroller.IEditControlAdapter):
-    __select__ = implements('CWProperty')
+    __select__ = is_instance('CWProperty')
 
     def after_deletion_path(self):
         """return (path, parameters) which should be used as redirect
--- a/web/views/cwuser.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/cwuser.py	Mon Jul 05 12:04:32 2010 +0200
@@ -21,7 +21,7 @@
 
 from logilab.mtconverter import xml_escape
 
-from cubicweb.selectors import one_line_rset, implements, match_user_groups
+from cubicweb.selectors import one_line_rset, is_instance, match_user_groups
 from cubicweb.view import EntityView
 from cubicweb.web import action, uicfg
 from cubicweb.web.views import tabs
@@ -38,7 +38,7 @@
 
 class UserPreferencesEntityAction(action.Action):
     __regid__ = 'prefs'
-    __select__ = (one_line_rset() & implements('CWUser') &
+    __select__ = (one_line_rset() & is_instance('CWUser') &
                   match_user_groups('owners', 'managers'))
 
     title = _('preferences')
@@ -51,7 +51,7 @@
 
 class FoafView(EntityView):
     __regid__ = 'foaf'
-    __select__ = implements('CWUser')
+    __select__ = is_instance('CWUser')
 
     title = _('foaf')
     templatable = False
@@ -93,14 +93,14 @@
 
 
 class CWGroupPrimaryView(tabs.TabbedPrimaryView):
-    __select__ = implements('CWGroup')
+    __select__ = is_instance('CWGroup')
     tabs = [_('cwgroup-main'), _('cwgroup-permissions')]
     default_tab = 'cwgroup-main'
 
 
 class CWGroupMainTab(tabs.PrimaryTab):
     __regid__ = 'cwgroup-main'
-    __select__ = tabs.PrimaryTab.__select__ & implements('CWGroup')
+    __select__ = tabs.PrimaryTab.__select__ & is_instance('CWGroup')
 
     def render_entity_attributes(self, entity):
         rql = 'Any U, FN, LN, CD, LL ORDERBY L WHERE U in_group G, ' \
@@ -114,7 +114,7 @@
 
 class CWGroupPermTab(EntityView):
     __regid__ = 'cwgroup-permissions'
-    __select__ = implements('CWGroup')
+    __select__ = is_instance('CWGroup')
 
     def cell_call(self, row, col):
         self._cw.add_css(('cubicweb.schema.css','cubicweb.acl.css'))
@@ -140,7 +140,7 @@
 
 class CWGroupInContextView(EntityView):
     __regid__ = 'incontext'
-    __select__ = implements('CWGroup')
+    __select__ = is_instance('CWGroup')
 
     def cell_call(self, row, col):
         entity = self.cw_rset.complete_entity(row, col)
--- a/web/views/editcontroller.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/editcontroller.py	Mon Jul 05 12:04:32 2010 +0200
@@ -27,7 +27,7 @@
 
 from cubicweb import Binary, ValidationError, typed_eid
 from cubicweb.view import EntityAdapter, implements_adapter_compat
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.web import (INTERNAL_FIELD_VALUE, RequestError, NothingToEdit,
                           ProcessFormError)
 from cubicweb.web.views import basecontrollers, autoform
@@ -35,7 +35,7 @@
 
 class IEditControlAdapter(EntityAdapter):
     __regid__ = 'IEditControl'
-    __select__ = implements('Any')
+    __select__ = is_instance('Any')
 
     @implements_adapter_compat('IEditControl')
     def after_deletion_path(self):
--- a/web/views/editforms.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/editforms.py	Mon Jul 05 12:04:32 2010 +0200
@@ -30,7 +30,7 @@
 
 from cubicweb import tags
 from cubicweb.selectors import (match_kwargs, one_line_rset, non_final_entity,
-                                specified_etype_implements, implements, yes)
+                                specified_etype_implements, is_instance, yes)
 from cubicweb.view import EntityView
 from cubicweb.schema import display_name
 from cubicweb.web import uicfg, stdmsgs, eid_param, dumps, \
@@ -44,7 +44,7 @@
 class DeleteConfForm(forms.CompositeForm):
     __regid__ = 'deleteconf'
     # XXX non_final_entity does not implement eclass_selector
-    __select__ = implements('Any')
+    __select__ = is_instance('Any')
 
     domid = 'deleteconf'
     copy_nav_params = True
--- a/web/views/emailaddress.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/emailaddress.py	Mon Jul 05 12:04:32 2010 +0200
@@ -23,7 +23,7 @@
 from logilab.mtconverter import xml_escape
 
 from cubicweb.schema import display_name
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb import Unauthorized
 from cubicweb.web import uicfg
 from cubicweb.web.views import baseviews, primary, ibreadcrumbs
@@ -33,7 +33,7 @@
 _pvs.tag_subject_of(('*', 'primary_email', '*'), 'hidden')
 
 class EmailAddressPrimaryView(primary.PrimaryView):
-    __select__ = implements('EmailAddress')
+    __select__ = is_instance('EmailAddress')
 
     def cell_call(self, row, col, skipeids=None):
         self.skipeids = skipeids
@@ -72,7 +72,7 @@
 
 
 class EmailAddressShortPrimaryView(EmailAddressPrimaryView):
-    __select__ = implements('EmailAddress')
+    __select__ = is_instance('EmailAddress')
     __regid__ = 'shortprimary'
     title = None # hidden view
 
@@ -83,7 +83,7 @@
 
 
 class EmailAddressOneLineView(baseviews.OneLineView):
-    __select__ = implements('EmailAddress')
+    __select__ = is_instance('EmailAddress')
 
     def cell_call(self, row, col, **kwargs):
         entity = self.cw_rset.get_entity(row, col)
@@ -104,7 +104,7 @@
     'mailto:'"""
 
     __regid__ = 'mailto'
-    __select__ = implements('EmailAddress')
+    __select__ = is_instance('EmailAddress')
 
     def cell_call(self, row, col, **kwargs):
         entity = self.cw_rset.get_entity(row, col)
@@ -127,21 +127,21 @@
 
 
 class EmailAddressInContextView(baseviews.InContextView):
-    __select__ = implements('EmailAddress')
+    __select__ = is_instance('EmailAddress')
 
     def cell_call(self, row, col, **kwargs):
         self.wview('mailto', self.cw_rset, row=row, col=col, **kwargs)
 
 
 class EmailAddressTextView(baseviews.TextView):
-    __select__ = implements('EmailAddress')
+    __select__ = is_instance('EmailAddress')
 
     def cell_call(self, row, col, **kwargs):
         self.w(self.cw_rset.get_entity(row, col).display_address())
 
 
 class EmailAddressIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('EmailAddress')
+    __select__ = is_instance('EmailAddress')
 
     def parent_entity(self):
         return self.entity.email_of
--- a/web/views/formrenderers.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/formrenderers.py	Mon Jul 05 12:04:32 2010 +0200
@@ -40,7 +40,7 @@
 
 from cubicweb import tags
 from cubicweb.appobject import AppObject
-from cubicweb.selectors import implements, yes
+from cubicweb.selectors import is_instance, yes
 from cubicweb.web import dumps, eid_param, formwidgets as fwdgs
 
 
@@ -392,7 +392,7 @@
     """
     __regid__ = 'default'
     # needs some additional points in some case (XXX explain cases)
-    __select__ = implements('Any') & yes()
+    __select__ = is_instance('Any') & yes()
 
     _options = FormRenderer._options + ('main_form_title',)
     main_form_title = _('main informations')
--- a/web/views/ibreadcrumbs.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/ibreadcrumbs.py	Mon Jul 05 12:04:32 2010 +0200
@@ -25,7 +25,7 @@
 from logilab.mtconverter import xml_escape
 
 #from cubicweb.interfaces import IBreadCrumbs
-from cubicweb.selectors import (implements, one_line_rset, adaptable,
+from cubicweb.selectors import (is_instance, one_line_rset, adaptable,
                                 one_etype_rset, multi_lines_rset, any_rset)
 from cubicweb.view import EntityView, Component, EntityAdapter
 # don't use AnyEntity since this may cause bug with isinstance() due to reloading
@@ -48,7 +48,7 @@
     the web ui
     """
     __regid__ = 'IBreadCrumbs'
-    __select__ = implements('Any', accept_none=False)
+    __select__ = is_instance('Any', accept_none=False)
 
     def parent_entity(self):
         if hasattr(self.entity, 'parent'):
--- a/web/views/idownloadable.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/idownloadable.py	Mon Jul 05 12:04:32 2010 +0200
@@ -23,7 +23,7 @@
 from logilab.mtconverter import BINARY_ENCODINGS, TransformError, xml_escape
 
 from cubicweb.view import EntityView
-from cubicweb.selectors import (one_line_rset, implements, match_context_prop,
+from cubicweb.selectors import (one_line_rset, is_instance, match_context_prop,
                                 adaptable, has_mimetype)
 from cubicweb.mttransforms import ENGINE
 from cubicweb.web import box, httpcache
--- a/web/views/igeocodable.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/igeocodable.py	Mon Jul 05 12:04:32 2010 +0200
@@ -15,9 +15,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""Specific views for entities implementing IGeocodable
+"""Specific views for entities implementing IGeocodable"""
 
-"""
 __docformat__ = "restructuredtext en"
 
 from cubicweb.interfaces import IGeocodable
--- a/web/views/massmailing.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/massmailing.py	Mon Jul 05 12:04:32 2010 +0200
@@ -22,7 +22,7 @@
 
 import operator
 
-from cubicweb.selectors import (implements, authenticated_user,
+from cubicweb.selectors import (is_instance, authenticated_user,
                                 adaptable, match_form_params)
 from cubicweb.view import EntityView
 from cubicweb.web import (Redirect, stdmsgs, controller, action,
--- a/web/views/schema.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/schema.py	Mon Jul 05 12:04:32 2010 +0200
@@ -30,7 +30,7 @@
 from yams import BASE_TYPES, schema2dot as s2d
 from yams.buildobjs import DEFAULT_ATTRPERMS
 
-from cubicweb.selectors import (implements, match_user_groups, match_kwargs,
+from cubicweb.selectors import (is_instance, match_user_groups, match_kwargs,
                                 has_related_entities, authenticated_user, yes)
 from cubicweb.schema import (META_RTYPES, SCHEMA_TYPES, SYSTEM_RTYPES,
                              WORKFLOW_TYPES, INTERNAL_TYPES)
@@ -289,7 +289,7 @@
 _('i18ncard_1'), _('i18ncard_?'), _('i18ncard_+'), _('i18ncard_*')
 
 class CWETypePrimaryView(tabs.TabbedPrimaryView):
-    __select__ = implements('CWEType')
+    __select__ = is_instance('CWEType')
     tabs = [_('cwetype-description'), _('cwetype-box'), _('cwetype-workflow'),
             _('cwetype-views'), _('cwetype-permissions')]
     default_tab = 'cwetype-description'
@@ -297,7 +297,7 @@
 
 class CWETypeDescriptionTab(tabs.PrimaryTab):
     __regid__ = 'cwetype-description'
-    __select__ = tabs.PrimaryTab.__select__ & implements('CWEType')
+    __select__ = tabs.PrimaryTab.__select__ & is_instance('CWEType')
 
     def render_entity_attributes(self, entity):
         super(CWETypeDescriptionTab, self).render_entity_attributes(entity)
@@ -379,7 +379,7 @@
 
 class CWETypeBoxTab(EntityView):
     __regid__ = 'cwetype-box'
-    __select__ = implements('CWEType')
+    __select__ = is_instance('CWEType')
 
     def cell_call(self, row, col):
         viewer = schemaviewer.SchemaViewer(self._cw)
@@ -392,7 +392,7 @@
 
 class CWETypePermTab(SecurityViewMixIn, EntityView):
     __regid__ = 'cwetype-permissions'
-    __select__ = implements('CWEType') & authenticated_user()
+    __select__ = is_instance('CWEType') & authenticated_user()
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
@@ -412,7 +412,7 @@
 
 class CWETypeWorkflowTab(EntityView):
     __regid__ = 'cwetype-workflow'
-    __select__ = (implements('CWEType')
+    __select__ = (is_instance('CWEType')
                   & has_related_entities('workflow_of', 'object'))
 
     def cell_call(self, row, col):
@@ -443,7 +443,7 @@
 class CWETypeViewsTab(EntityView):
     """possible views for this entity type"""
     __regid__ = 'cwetype-views'
-    __select__ = EntityView.__select__ & implements('CWEType')
+    __select__ = EntityView.__select__ & is_instance('CWEType')
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
@@ -463,7 +463,7 @@
 
 
 class CWETypeOneLineView(baseviews.OneLineView):
-    __select__ = implements('CWEType')
+    __select__ = is_instance('CWEType')
 
     def cell_call(self, row, col, **kwargs):
         entity = self.cw_rset.get_entity(row, col)
@@ -477,14 +477,14 @@
 # CWRType ######################################################################
 
 class CWRTypePrimaryView(tabs.TabbedPrimaryView):
-    __select__ = implements('CWRType')
+    __select__ = is_instance('CWRType')
     tabs = [_('cwrtype-description'), _('cwrtype-permissions')]
     default_tab = 'cwrtype-description'
 
 
 class CWRTypeDescriptionTab(tabs.PrimaryTab):
     __regid__ = 'cwrtype-description'
-    __select__ = implements('CWRType')
+    __select__ = is_instance('CWRType')
 
     def render_entity_attributes(self, entity):
         super(CWRTypeDescriptionTab, self).render_entity_attributes(entity)
@@ -503,7 +503,7 @@
 
 class CWRTypePermTab(SecurityViewMixIn, EntityView):
     __regid__ = 'cwrtype-permissions'
-    __select__ = implements('CWRType') & authenticated_user()
+    __select__ = is_instance('CWRType') & authenticated_user()
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
@@ -514,14 +514,14 @@
 # CWAttribute / CWRelation #####################################################
 
 class RDEFPrimaryView(tabs.TabbedPrimaryView):
-    __select__ = implements('CWRelation', 'CWAttribute')
+    __select__ = is_instance('CWRelation', 'CWAttribute')
     tabs = [_('rdef-description'), _('rdef-permissions')]
     default_tab = 'rdef-description'
 
 
 class RDEFDescriptionTab(tabs.PrimaryTab):
     __regid__ = 'rdef-description'
-    __select__ = implements('CWRelation', 'CWAttribute')
+    __select__ = is_instance('CWRelation', 'CWAttribute')
 
     def render_entity_attributes(self, entity):
         super(RDEFDescriptionTab, self).render_entity_attributes(entity)
@@ -533,7 +533,7 @@
 
 class RDEFPermTab(SecurityViewMixIn, EntityView):
     __regid__ = 'rdef-permissions'
-    __select__ = implements('CWRelation', 'CWAttribute') & authenticated_user()
+    __select__ = is_instance('CWRelation', 'CWAttribute') & authenticated_user()
 
     def cell_call(self, row, col):
         self.permissions_table(self.cw_rset.get_entity(row, col).yams_schema())
@@ -545,7 +545,7 @@
     for instance)
     """
     __regid__ = 'rdef-name-cell'
-    __select__ = implements('CWRelation', 'CWAttribute')
+    __select__ = is_instance('CWRelation', 'CWAttribute')
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
@@ -558,7 +558,7 @@
     """same as RDEFNameView but when the context is the object entity
     """
     __regid__ = 'rdef-object-name-cell'
-    __select__ = implements('CWRelation', 'CWAttribute')
+    __select__ = is_instance('CWRelation', 'CWAttribute')
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
@@ -569,7 +569,7 @@
 
 class RDEFConstraintsCell(EntityView):
     __regid__ = 'rdef-constraints-cell'
-    __select__ = implements('CWAttribute', 'CWRelation')
+    __select__ = is_instance('CWAttribute', 'CWRelation')
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
@@ -580,7 +580,7 @@
 
 class CWAttributeOptionsCell(EntityView):
     __regid__ = 'rdef-options-cell'
-    __select__ = implements('CWAttribute')
+    __select__ = is_instance('CWAttribute')
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
@@ -595,7 +595,7 @@
 
 class CWRelationOptionsCell(EntityView):
     __regid__ = 'rdef-options-cell'
-    __select__ = implements('CWRelation',)
+    __select__ = is_instance('CWRelation',)
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
@@ -753,28 +753,28 @@
 # breadcrumbs ##################################################################
 
 class CWRelationIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('CWRelation')
+    __select__ = is_instance('CWRelation')
     def parent_entity(self):
         return self.entity.rtype
 
 class CWAttributeIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('CWAttribute')
+    __select__ = is_instance('CWAttribute')
     def parent_entity(self):
         return self.entity.stype
 
 class CWConstraintIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('CWConstraint')
+    __select__ = is_instance('CWConstraint')
     def parent_entity(self):
         if self.entity.reverse_constrained_by:
             return self.entity.reverse_constrained_by[0]
 
 class RQLExpressionIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('RQLExpression')
+    __select__ = is_instance('RQLExpression')
     def parent_entity(self):
         return self.entity.expression_of
 
 class CWPermissionIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('CWPermission')
+    __select__ = is_instance('CWPermission')
     def parent_entity(self):
         # XXX useless with permission propagation
         permissionof = getattr(self.entity, 'reverse_require_permission', ())
@@ -786,7 +786,7 @@
 
 class CWFinalFacet(facet.AttributeFacet):
     __regid__ = 'cwfinal-facet'
-    __select__ = facet.AttributeFacet.__select__ & implements('CWEType', 'CWRType')
+    __select__ = facet.AttributeFacet.__select__ & is_instance('CWEType', 'CWRType')
     rtype = 'final'
 
 class ViewSchemaAction(action.Action):
--- a/web/views/startup.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/startup.py	Mon Jul 05 12:04:32 2010 +0200
@@ -26,7 +26,7 @@
 from logilab.mtconverter import xml_escape
 
 from cubicweb.view import StartupView
-from cubicweb.selectors import match_user_groups, implements
+from cubicweb.selectors import match_user_groups, is_instance
 from cubicweb.schema import display_name
 from cubicweb.web import ajax_replace_url, uicfg, httpcache
 
--- a/web/views/tabs.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/tabs.py	Mon Jul 05 12:04:32 2010 +0200
@@ -175,7 +175,7 @@
     class ProjectScreenshotsView(EntityRelationView):
         '''display project's screenshots'''
         __regid__ = title = _('projectscreenshots')
-        __select__ = EntityRelationView.__select__ & implements('Project')
+        __select__ = EntityRelationView.__select__ & is_instance('Project')
         rtype = 'screenshot'
         role = 'subject'
         vid = 'gallery'
--- a/web/views/vcard.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/vcard.py	Mon Jul 05 12:04:32 2010 +0200
@@ -20,7 +20,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.view import EntityView
 
 _ = unicode
@@ -33,7 +33,7 @@
     title = _('vcard')
     templatable = False
     content_type = 'text/x-vcard'
-    __select__ = implements('CWUser')
+    __select__ = is_instance('CWUser')
 
     def set_request_content_type(self):
         """overriden to set a .vcf filename"""
--- a/web/views/workflow.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/workflow.py	Mon Jul 05 12:04:32 2010 +0200
@@ -31,9 +31,9 @@
 from logilab.common.graph import escape, GraphGenerator, DotBackend
 
 from cubicweb import Unauthorized, view
-from cubicweb.selectors import (implements, has_related_entities, one_line_rset,
+from cubicweb.selectors import (has_related_entities, one_line_rset,
                                 relation_possible, match_form_params,
-                                implements, score_entity, adaptable)
+                                score_entity, is_instance, adaptable)
 from cubicweb.utils import make_uid
 from cubicweb.view import EntityView
 from cubicweb.schema import display_name
@@ -226,14 +226,14 @@
 _abaa.tag_object_of(('WorkflowTransition', 'transition_of', 'Workflow'), True)
 
 class WorkflowPrimaryView(TabbedPrimaryView):
-    __select__ = implements('Workflow')
+    __select__ = is_instance('Workflow')
     tabs = [  _('wf_tab_info'), _('wfgraph'),]
     default_tab = 'wf_tab_info'
 
 
 class CellView(view.EntityView):
     __regid__ = 'cell'
-    __select__ = implements('TrInfo')
+    __select__ = is_instance('TrInfo')
 
     def cell_call(self, row, col, cellvid=None):
         self.w(self.cw_rset.get_entity(row, col).view('reledit', rtype='comment'))
@@ -242,7 +242,7 @@
 class StateInContextView(view.EntityView):
     """convenience trick, State's incontext view should not be clickable"""
     __regid__ = 'incontext'
-    __select__ = implements('State')
+    __select__ = is_instance('State')
 
     def cell_call(self, row, col):
         self.w(xml_escape(self._cw.view('textincontext', self.cw_rset,
@@ -250,7 +250,7 @@
 
 class WorkflowTabTextView(PrimaryTab):
     __regid__ = 'wf_tab_info'
-    __select__ = PrimaryTab.__select__ & one_line_rset() & implements('Workflow')
+    __select__ = PrimaryTab.__select__ & one_line_rset() & is_instance('Workflow')
 
     def render_entity_attributes(self, entity):
         _ = self._cw._
@@ -276,7 +276,7 @@
 
 class TransitionSecurityTextView(view.EntityView):
     __regid__ = 'trsecurity'
-    __select__ = implements('Transition')
+    __select__ = is_instance('Transition')
 
     def cell_call(self, row, col):
         _ = self._cw._
@@ -294,7 +294,7 @@
 
 class TransitionAllowedTextView(view.EntityView):
     __regid__ = 'trfromstates'
-    __select__ = implements('Transition')
+    __select__ = is_instance('Transition')
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(self.cw_row, self.cw_col)
@@ -319,7 +319,7 @@
 
 
 class TransitionEditionForm(autoform.AutomaticEntityForm):
-    __select__ = implements('Transition')
+    __select__ = is_instance('Transition')
 
     def workflow_states_for_relation(self, targetrelation):
         eids = self.edited_entity.linked_to('transition_of', 'subject')
@@ -340,7 +340,7 @@
 
 
 class StateEditionForm(autoform.AutomaticEntityForm):
-    __select__ = implements('State')
+    __select__ = is_instance('State')
 
     def subject_allowed_transition_vocabulary(self, rtype, limit=None):
         if not self.edited_entity.has_eid():
@@ -351,23 +351,23 @@
         return []
 
 class WorkflowIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('Workflow')
+    __select__ = is_instance('Workflow')
     # XXX what if workflow of multiple types?
     def parent_entity(self):
         return self.entity.workflow_of and self.entity.workflow_of[0] or None
 
 class WorkflowItemIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('BaseTransition', 'State')
+    __select__ = is_instance('BaseTransition', 'State')
     def parent_entity(self):
         return self.entity.workflow
 
 class TransitionItemIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('SubWorkflowExitPoint')
+    __select__ = is_instance('SubWorkflowExitPoint')
     def parent_entity(self):
         return self.entity.reverse_subworkflow_exit[0]
 
 class TrInfoIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = implements('TrInfo')
+    __select__ = is_instance('TrInfo')
     def parent_entity(self):
         return self.entity.for_entity
 
@@ -424,7 +424,7 @@
 
 class WorkflowGraphView(view.EntityView):
     __regid__ = 'wfgraph'
-    __select__ = EntityView.__select__ & one_line_rset() & implements('Workflow')
+    __select__ = EntityView.__select__ & one_line_rset() & is_instance('Workflow')
 
     def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
--- a/web/views/xbel.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/xbel.py	Mon Jul 05 12:04:32 2010 +0200
@@ -23,7 +23,7 @@
 
 from logilab.mtconverter import xml_escape
 
-from cubicweb.selectors import implements
+from cubicweb.selectors import is_instance
 from cubicweb.view import EntityView
 from cubicweb.web.views.xmlrss import XMLView
 
@@ -62,7 +62,7 @@
 
 
 class XbelItemBookmarkView(XbelItemView):
-    __select__ = implements('Bookmark')
+    __select__ = is_instance('Bookmark')
 
     def url(self, entity):
         return entity.actual_url()
--- a/web/views/xmlrss.py	Fri Jul 02 19:14:48 2010 +0200
+++ b/web/views/xmlrss.py	Mon Jul 05 12:04:32 2010 +0200
@@ -24,7 +24,7 @@
 
 from logilab.mtconverter import xml_escape
 
-from cubicweb.selectors import (implements, non_final_entity, one_line_rset,
+from cubicweb.selectors import (is_instance, non_final_entity, one_line_rset,
                                 appobject_selectable, adaptable)
 from cubicweb.view import EntityView, EntityAdapter, AnyRsetView, Component
 from cubicweb.view import implements_adapter_compat
@@ -123,7 +123,7 @@
 
 class IFeedAdapter(EntityAdapter):
     __regid__ = 'IFeed'
-    __select__ = implements('Any')
+    __select__ = is_instance('Any')
 
     @implements_adapter_compat('IFeed')
     def rss_feed_url(self):